config_add.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. package config
  2. import (
  3. "context"
  4. "encoding/json"
  5. "errors"
  6. "os"
  7. "path/filepath"
  8. "github.com/0xJacky/Nginx-UI/internal/config"
  9. "github.com/0xJacky/Nginx-UI/internal/helper"
  10. "github.com/0xJacky/Nginx-UI/internal/nginx"
  11. "github.com/0xJacky/Nginx-UI/model"
  12. "github.com/0xJacky/Nginx-UI/query"
  13. "github.com/mark3labs/mcp-go/mcp"
  14. )
  15. const nginxConfigAddToolName = "nginx_config_add"
  16. // ErrFileAlreadyExists is returned when trying to create a file that already exists
  17. var ErrFileAlreadyExists = errors.New("file already exists")
  18. var nginxConfigAddTool = mcp.NewTool(
  19. nginxConfigAddToolName,
  20. mcp.WithDescription("Add or create a new Nginx configuration file"),
  21. mcp.WithString("name", mcp.Description("The name of the configuration file to create")),
  22. mcp.WithString("content", mcp.Description("The content of the configuration file")),
  23. mcp.WithString("base_dir", mcp.Description("The base directory for the configuration")),
  24. mcp.WithBoolean("overwrite", mcp.Description("Whether to overwrite an existing file")),
  25. mcp.WithArray("sync_node_ids", mcp.Description("IDs of nodes to sync the configuration to")),
  26. )
  27. func handleNginxConfigAdd(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
  28. args := request.Params.Arguments
  29. name := args["name"].(string)
  30. content := args["content"].(string)
  31. baseDir := args["base_dir"].(string)
  32. overwrite := args["overwrite"].(bool)
  33. // Convert sync_node_ids from []interface{} to []uint64
  34. syncNodeIdsInterface, ok := args["sync_node_ids"].([]interface{})
  35. syncNodeIds := make([]uint64, 0)
  36. if ok {
  37. for _, id := range syncNodeIdsInterface {
  38. if idFloat, ok := id.(float64); ok {
  39. syncNodeIds = append(syncNodeIds, uint64(idFloat))
  40. }
  41. }
  42. }
  43. dir := nginx.GetConfPath(baseDir)
  44. path := filepath.Join(dir, name)
  45. if !helper.IsUnderDirectory(path, nginx.GetConfPath()) {
  46. return nil, config.ErrPathIsNotUnderTheNginxConfDir
  47. }
  48. if !overwrite && helper.FileExists(path) {
  49. return nil, ErrFileAlreadyExists
  50. }
  51. // Check if the directory exists, if not, create it
  52. if !helper.FileExists(dir) {
  53. err := os.MkdirAll(dir, 0755)
  54. if err != nil {
  55. return nil, err
  56. }
  57. }
  58. err := os.WriteFile(path, []byte(content), 0644)
  59. if err != nil {
  60. return nil, err
  61. }
  62. output, err := nginx.Reload()
  63. if err != nil {
  64. return nil, err
  65. }
  66. if nginx.GetLogLevel(output) >= nginx.Warn {
  67. return nil, config.ErrNginxReloadFailed
  68. }
  69. q := query.Config
  70. _, err = q.Where(q.Filepath.Eq(path)).Delete()
  71. if err != nil {
  72. return nil, err
  73. }
  74. cfg := &model.Config{
  75. Name: name,
  76. Filepath: path,
  77. SyncNodeIds: syncNodeIds,
  78. SyncOverwrite: overwrite,
  79. }
  80. err = q.Create(cfg)
  81. if err != nil {
  82. return nil, err
  83. }
  84. err = config.SyncToRemoteServer(cfg)
  85. if err != nil {
  86. return nil, err
  87. }
  88. result := map[string]interface{}{
  89. "name": name,
  90. "content": content,
  91. "file_path": path,
  92. }
  93. jsonResult, _ := json.Marshal(result)
  94. return mcp.NewToolResultText(string(jsonResult)), nil
  95. }