cloudpods_vpcs_tool.go 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package tools
  15. import (
  16. "context"
  17. "encoding/json"
  18. "fmt"
  19. "strconv"
  20. "github.com/mark3labs/mcp-go/mcp"
  21. "yunion.io/x/log"
  22. "yunion.io/x/onecloud/pkg/mcp-server/adapters"
  23. "yunion.io/x/onecloud/pkg/mcp-server/models"
  24. )
  25. // CloudpodsVPCsTool 用于查询Cloudpods VPC列表的工具
  26. //
  27. // 字段:
  28. // - adapter: 用于与Cloudpods API进行交互的适配器
  29. type CloudpodsVPCsTool struct {
  30. adapter *adapters.CloudpodsAdapter
  31. }
  32. // NewCloudpodsVPCsTool 创建CloudpodsVPCsTool实例
  33. //
  34. // 参数:
  35. // - adapter: 用于与Cloudpods API交互的适配器
  36. //
  37. // 返回值:
  38. // - *CloudpodsVPCsTool: CloudpodsVPCsTool实例指针
  39. func NewCloudpodsVPCsTool(adapter *adapters.CloudpodsAdapter) *CloudpodsVPCsTool {
  40. return &CloudpodsVPCsTool{
  41. adapter: adapter,
  42. }
  43. }
  44. // GetTool 定义并返回查询VPC列表工具的元数据
  45. //
  46. // 工具用途:
  47. //
  48. // 查询Cloudpods VPC列表,获取虚拟私有网络信息
  49. //
  50. // 参数说明:
  51. // - limit: 返回结果数量限制,默认为20
  52. // - offset: 返回结果偏移量,默认为0
  53. // - search: 搜索关键词,可以按VPC名称搜索
  54. // - cloudregion_id: 过滤指定云区域的VPC资源
  55. // - ak: 用户登录cloudpods后获取的access key
  56. // - sk: 用户登录cloudpods后获取的secret key
  57. func (c *CloudpodsVPCsTool) GetTool() mcp.Tool {
  58. return mcp.NewTool(
  59. "cloudpods_list_vpcs",
  60. mcp.WithDescription("查询Cloudpods VPC列表,获取虚拟私有网络信息"),
  61. mcp.WithString("limit", mcp.Description("返回结果数量限制,默认为20")),
  62. mcp.WithString("offset", mcp.Description("返回结果偏移量,默认为0")),
  63. mcp.WithString("search", mcp.Description("搜索关键词,可以按VPC名称搜索")),
  64. mcp.WithString("cloudregion_id", mcp.Description("过滤指定云区域的VPC资源")),
  65. mcp.WithString("ak", mcp.Description("用户登录cloudpods后获取的access key")),
  66. mcp.WithString("sk", mcp.Description("用户登录cloudpods后获取的secret key")),
  67. )
  68. }
  69. // Handle 处理查询VPC列表的请求
  70. //
  71. // 参数:
  72. // - ctx: 控制生命周期的上下文
  73. // - req: 包含查询参数的请求对象
  74. //
  75. // 返回值:
  76. // - *mcp.CallToolResult: 包含VPC列表的响应对象
  77. // - error: 可能的错误信息
  78. func (c *CloudpodsVPCsTool) Handle(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
  79. // 获取可选参数:返回结果数量限制,如果指定则转换为整数
  80. limit := 20
  81. if limitStr := req.GetString("limit", ""); limitStr != "" {
  82. if parsedLimit, err := strconv.Atoi(limitStr); err == nil && parsedLimit > 0 {
  83. limit = parsedLimit
  84. }
  85. }
  86. // 获取可选参数:结果偏移量,如果指定则转换为整数
  87. offset := 0
  88. if offsetStr := req.GetString("offset", ""); offsetStr != "" {
  89. if parsedOffset, err := strconv.Atoi(offsetStr); err == nil && parsedOffset >= 0 {
  90. offset = parsedOffset
  91. }
  92. }
  93. // 获取可选参数:搜索关键词
  94. search := req.GetString("search", "")
  95. // 获取可选参数:云区域ID
  96. cloudRegionID := req.GetString("cloudregion_id", "")
  97. // 获取可选参数:访问凭证
  98. ak := req.GetString("ak", "")
  99. sk := req.GetString("sk", "")
  100. // 调用适配器查询VPC列表
  101. vpcsResponse, err := c.adapter.ListVPCs(ctx, limit, offset, search, cloudRegionID, ak, sk)
  102. if err != nil {
  103. log.Errorf("Fail to query vpc: %s", err)
  104. return nil, fmt.Errorf("fail to query vpc: %w", err)
  105. }
  106. // 格式化查询结果
  107. formattedResult := c.formatVPCsResult(vpcsResponse, limit, offset, search, cloudRegionID)
  108. // 将结果序列化为JSON格式
  109. resultJSON, err := json.MarshalIndent(formattedResult, "", " ")
  110. if err != nil {
  111. log.Errorf("Fail to serialize result: %s", err)
  112. return nil, fmt.Errorf("fail to serialize result: %w", err)
  113. }
  114. return mcp.NewToolResultText(string(resultJSON)), nil
  115. }
  116. // GetName 返回工具的名称标识符
  117. //
  118. // 返回值:
  119. // - string: 工具名称字符串,用于唯一标识该工具
  120. func (c *CloudpodsVPCsTool) GetName() string {
  121. return "cloudpods_list_vpcs"
  122. }
  123. // formatVPCsResult 格式化VPC列表的响应结果
  124. //
  125. // 参数:
  126. // - response: 原始响应数据
  127. // - limit: 查询限制
  128. // - offset: 查询偏移量
  129. // - search: 搜索关键词
  130. // - cloudRegionID: 云区域ID
  131. //
  132. // 返回值:
  133. // - map[string]interface{}: 包含VPC列表的格式化结果
  134. func (c *CloudpodsVPCsTool) formatVPCsResult(response *models.VpcListResponse, limit, offset int, search, cloudRegionID string) map[string]interface{} {
  135. // 初始化格式化结果结构
  136. formatted := map[string]interface{}{
  137. "query_info": map[string]interface{}{
  138. "limit": limit,
  139. "offset": offset,
  140. "search": search,
  141. "cloudregion_id": cloudRegionID,
  142. "total": response.Total,
  143. "count": len(response.Vpcs),
  144. },
  145. "vpcs": make([]map[string]interface{}, 0, len(response.Vpcs)),
  146. }
  147. // 遍历VPC列表,构造每个VPC的详细信息
  148. for _, vpc := range response.Vpcs {
  149. vpcInfo := map[string]interface{}{
  150. "id": vpc.Id,
  151. "name": vpc.Name,
  152. "description": vpc.Description,
  153. "cidr_block": vpc.CidrBlock,
  154. "cidr_block6": vpc.CidrBlock6,
  155. "status": vpc.Status,
  156. "enabled": vpc.Enabled,
  157. "is_default": vpc.IsDefault,
  158. "is_public": vpc.IsPublic,
  159. "provider": vpc.Provider,
  160. "brand": vpc.Brand,
  161. "cloud_env": vpc.CloudEnv,
  162. "environment": vpc.Environment,
  163. "cloudregion": vpc.Cloudregion,
  164. "cloudregion_id": vpc.CloudregionId,
  165. "region": vpc.Region,
  166. "region_id": vpc.RegionId,
  167. "external_id": vpc.ExternalId,
  168. "external_access_mode": vpc.ExternalAccessMode,
  169. "globalvpc": vpc.Globalvpc,
  170. "globalvpc_id": vpc.GlobalvpcId,
  171. "account": vpc.Account,
  172. "account_id": vpc.AccountId,
  173. "account_status": vpc.AccountStatus,
  174. "account_health_status": vpc.AccountHealthStatus,
  175. "manager": vpc.Manager,
  176. "manager_id": vpc.ManagerId,
  177. "manager_domain": vpc.ManagerDomain,
  178. "manager_domain_id": vpc.ManagerDomainId,
  179. "manager_project": vpc.ManagerProject,
  180. "manager_project_id": vpc.ManagerProjectId,
  181. "network_count": vpc.NetworkCount,
  182. "wire_count": vpc.WireCount,
  183. "dns_zone_count": vpc.DnsZoneCount,
  184. "natgateway_count": vpc.NatgatewayCount,
  185. "routetable_count": vpc.RoutetableCount,
  186. "accept_vpc_peer_count": vpc.AcceptVpcPeerCount,
  187. "request_vpc_peer_count": vpc.RequestVpcPeerCount,
  188. "direct": vpc.Direct,
  189. "domain_id": vpc.DomainId,
  190. "domain_src": vpc.DomainSrc,
  191. "project_domain": vpc.ProjectDomain,
  192. "public_scope": vpc.PublicScope,
  193. "public_src": vpc.PublicSrc,
  194. "region_ext_id": vpc.RegionExtId,
  195. "region_external_id": vpc.RegionExternalId,
  196. "source": vpc.Source,
  197. "progress": vpc.Progress,
  198. "shared_domains": vpc.SharedDomains,
  199. "shared_projects": vpc.SharedProjects,
  200. "can_delete": vpc.CanDelete,
  201. "can_update": vpc.CanUpdate,
  202. "is_emulated": vpc.IsEmulated,
  203. "metadata": vpc.Metadata,
  204. "created_at": vpc.CreatedAt,
  205. "updated_at": vpc.UpdatedAt,
  206. "imported_at": vpc.ImportedAt,
  207. }
  208. formatted["vpcs"] = append(formatted["vpcs"].([]map[string]interface{}), vpcInfo)
  209. }
  210. // 构造摘要信息
  211. formatted["summary"] = map[string]interface{}{
  212. "total_vpcs": response.Total,
  213. "returned_count": len(response.Vpcs),
  214. "has_more": response.Total > int64(offset+len(response.Vpcs)),
  215. "next_offset": offset + len(response.Vpcs),
  216. }
  217. return formatted
  218. }