dictionary_query.go 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. package mcpTool
  2. import (
  3. "context"
  4. "encoding/json"
  5. "fmt"
  6. "github.com/flipped-aurora/gin-vue-admin/server/global"
  7. "github.com/flipped-aurora/gin-vue-admin/server/model/system"
  8. "github.com/flipped-aurora/gin-vue-admin/server/service"
  9. "github.com/mark3labs/mcp-go/mcp"
  10. "go.uber.org/zap"
  11. "gorm.io/gorm"
  12. )
  13. // 注册工具
  14. func init() {
  15. RegisterTool(&DictionaryQuery{})
  16. }
  17. // DictionaryInfo 字典信息结构
  18. type DictionaryInfo struct {
  19. ID uint `json:"id"`
  20. Name string `json:"name"` // 字典名(中)
  21. Type string `json:"type"` // 字典名(英)
  22. Status *bool `json:"status"` // 状态
  23. Desc string `json:"desc"` // 描述
  24. Details []DictionaryDetailInfo `json:"details"` // 字典详情
  25. }
  26. // DictionaryDetailInfo 字典详情信息结构
  27. type DictionaryDetailInfo struct {
  28. ID uint `json:"id"`
  29. Label string `json:"label"` // 展示值
  30. Value string `json:"value"` // 字典值
  31. Extend string `json:"extend"` // 扩展值
  32. Status *bool `json:"status"` // 启用状态
  33. Sort int `json:"sort"` // 排序标记
  34. }
  35. // DictionaryQueryResponse 字典查询响应结构
  36. type DictionaryQueryResponse struct {
  37. Success bool `json:"success"`
  38. Message string `json:"message"`
  39. Total int `json:"total"`
  40. Dictionaries []DictionaryInfo `json:"dictionaries"`
  41. }
  42. // DictionaryQuery 字典查询工具
  43. type DictionaryQuery struct{}
  44. // New 创建字典查询工具
  45. func (d *DictionaryQuery) New() mcp.Tool {
  46. return mcp.NewTool("query_dictionaries",
  47. mcp.WithDescription("查询系统中所有的字典和字典属性,用于AI生成逻辑时了解可用的字典选项"),
  48. mcp.WithString("dictType",
  49. mcp.Description("可选:指定字典类型进行精确查询,如果不提供则返回所有字典"),
  50. ),
  51. mcp.WithBoolean("includeDisabled",
  52. mcp.Description("是否包含已禁用的字典和字典项,默认为false(只返回启用的)"),
  53. ),
  54. mcp.WithBoolean("detailsOnly",
  55. mcp.Description("是否只返回字典详情信息(不包含字典基本信息),默认为false"),
  56. ),
  57. )
  58. }
  59. // Handle 处理字典查询请求
  60. func (d *DictionaryQuery) Handle(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
  61. args := request.GetArguments()
  62. // 获取参数
  63. dictType := ""
  64. if val, ok := args["dictType"].(string); ok {
  65. dictType = val
  66. }
  67. includeDisabled := false
  68. if val, ok := args["includeDisabled"].(bool); ok {
  69. includeDisabled = val
  70. }
  71. detailsOnly := false
  72. if val, ok := args["detailsOnly"].(bool); ok {
  73. detailsOnly = val
  74. }
  75. // 获取字典服务
  76. dictionaryService := service.ServiceGroupApp.SystemServiceGroup.DictionaryService
  77. var dictionaries []DictionaryInfo
  78. var err error
  79. if dictType != "" {
  80. // 查询指定类型的字典
  81. var status *bool
  82. if !includeDisabled {
  83. status = &[]bool{true}[0]
  84. }
  85. sysDictionary, err := dictionaryService.GetSysDictionary(dictType, 0, status)
  86. if err != nil {
  87. global.GVA_LOG.Error("查询字典失败", zap.Error(err))
  88. return &mcp.CallToolResult{
  89. Content: []mcp.Content{
  90. mcp.NewTextContent(fmt.Sprintf(`{"success": false, "message": "查询字典失败: %v", "total": 0, "dictionaries": []}`, err.Error())),
  91. },
  92. }, nil
  93. }
  94. // 转换为响应格式
  95. dictInfo := DictionaryInfo{
  96. ID: sysDictionary.ID,
  97. Name: sysDictionary.Name,
  98. Type: sysDictionary.Type,
  99. Status: sysDictionary.Status,
  100. Desc: sysDictionary.Desc,
  101. }
  102. // 获取字典详情
  103. for _, detail := range sysDictionary.SysDictionaryDetails {
  104. if includeDisabled || (detail.Status != nil && *detail.Status) {
  105. dictInfo.Details = append(dictInfo.Details, DictionaryDetailInfo{
  106. ID: detail.ID,
  107. Label: detail.Label,
  108. Value: detail.Value,
  109. Extend: detail.Extend,
  110. Status: detail.Status,
  111. Sort: detail.Sort,
  112. })
  113. }
  114. }
  115. dictionaries = append(dictionaries, dictInfo)
  116. } else {
  117. // 查询所有字典
  118. var sysDictionaries []system.SysDictionary
  119. db := global.GVA_DB.Model(&system.SysDictionary{})
  120. if !includeDisabled {
  121. db = db.Where("status = ?", true)
  122. }
  123. err = db.Preload("SysDictionaryDetails", func(db *gorm.DB) *gorm.DB {
  124. if includeDisabled {
  125. return db.Order("sort")
  126. } else {
  127. return db.Where("status = ?", true).Order("sort")
  128. }
  129. }).Find(&sysDictionaries).Error
  130. if err != nil {
  131. global.GVA_LOG.Error("查询字典列表失败", zap.Error(err))
  132. return &mcp.CallToolResult{
  133. Content: []mcp.Content{
  134. mcp.NewTextContent(fmt.Sprintf(`{"success": false, "message": "查询字典列表失败: %v", "total": 0, "dictionaries": []}`, err.Error())),
  135. },
  136. }, nil
  137. }
  138. // 转换为响应格式
  139. for _, dict := range sysDictionaries {
  140. dictInfo := DictionaryInfo{
  141. ID: dict.ID,
  142. Name: dict.Name,
  143. Type: dict.Type,
  144. Status: dict.Status,
  145. Desc: dict.Desc,
  146. }
  147. // 获取字典详情
  148. for _, detail := range dict.SysDictionaryDetails {
  149. if includeDisabled || (detail.Status != nil && *detail.Status) {
  150. dictInfo.Details = append(dictInfo.Details, DictionaryDetailInfo{
  151. ID: detail.ID,
  152. Label: detail.Label,
  153. Value: detail.Value,
  154. Extend: detail.Extend,
  155. Status: detail.Status,
  156. Sort: detail.Sort,
  157. })
  158. }
  159. }
  160. dictionaries = append(dictionaries, dictInfo)
  161. }
  162. }
  163. // 如果只需要详情信息,则提取所有详情
  164. if detailsOnly {
  165. var allDetails []DictionaryDetailInfo
  166. for _, dict := range dictionaries {
  167. allDetails = append(allDetails, dict.Details...)
  168. }
  169. response := map[string]interface{}{
  170. "success": true,
  171. "message": "查询字典详情成功",
  172. "total": len(allDetails),
  173. "details": allDetails,
  174. }
  175. responseJSON, _ := json.Marshal(response)
  176. return &mcp.CallToolResult{
  177. Content: []mcp.Content{
  178. mcp.NewTextContent(string(responseJSON)),
  179. },
  180. }, nil
  181. }
  182. // 构建响应
  183. response := DictionaryQueryResponse{
  184. Success: true,
  185. Message: "查询字典成功",
  186. Total: len(dictionaries),
  187. Dictionaries: dictionaries,
  188. }
  189. responseJSON, err := json.Marshal(response)
  190. if err != nil {
  191. global.GVA_LOG.Error("序列化响应失败", zap.Error(err))
  192. return &mcp.CallToolResult{
  193. Content: []mcp.Content{
  194. mcp.NewTextContent(fmt.Sprintf(`{"success": false, "message": "序列化响应失败: %v", "total": 0, "dictionaries": []}`, err.Error())),
  195. },
  196. }, nil
  197. }
  198. return &mcp.CallToolResult{
  199. Content: []mcp.Content{
  200. mcp.NewTextContent(string(responseJSON)),
  201. },
  202. }, nil
  203. }