节点在线、应用在线、配置在线使用令牌查询
大石头 authored at 2021-12-16 19:49:30
3.40 KiB
Stardust
using System.Text.Json;
using NewLife;
using Stardust.Data;
using Stardust.Data.Platform;

namespace Stardust.Web.Mcp.Actions.Apps;

/// <summary>解析服务地址。查询指定服务的所有健康提供者,返回地址/版本/权重/标签</summary>
public class AppResolveServiceAction : McpActionBase
{
    /// <summary>动作名</summary>
    public override String Name => "app_resolve_service";

    /// <summary>动作描述</summary>
    public override String Description => "按服务名解析服务地址,返回所有健康的服务提供者(含地址/版本/权重/标签)。公开服务发现,无需资源授权。";

    /// <summary>所属模块</summary>
    public override McpModuleType Module => McpModuleType.App;

    /// <summary>所需资源授权。null表示无资源依赖(公开服务发现)</summary>
    public override ResourceRequirement? RequiredResource => null;

    /// <summary>输入参数JSON Schema</summary>
    public override JsonElement InputSchema
    {
        get
        {
            var json = """
            {
              "type": "object",
              "properties": {
                "service_name": {"type": "string", "description": "服务名"},
                "min_version": {"type": "string", "description": "可选,最低版本要求"},
                "tag": {"type": "string", "description": "可选,标签过滤(逗号分隔)"},
                "scope": {"type": "string", "description": "可选,作用域过滤"}
              },
              "required": ["service_name"]
            }
            """;
            using var doc = JsonDocument.Parse(json);
            return doc.RootElement.Clone();
        }
    }

    /// <summary>调用动作</summary>
    public override Task<Object> InvokeAsync(JsonElement @params, McpContext context)
    {
        var serviceName = GetString(@params, "service_name");
        if (serviceName.IsNullOrEmpty()) throw new McpException(-32602, "Invalid params: service_name is empty");

        var minVersion = GetString(@params, "min_version");
        var tag = GetString(@params, "tag");
        var scope = GetString(@params, "scope");

        // 查找服务实体
        var service = Service.FindByName(serviceName);
        if (service == null) throw new McpException(-32601, $"Service not found: {serviceName}");

        // 该服务的所有提供者
        var all = AppService.FindAllByService(service.Id);
        var tags = tag?.Split(",", StringSplitOptions.RemoveEmptyEntries);

        // 过滤:启用 + 健康 + 匹配规则(与 RegistryService.ResolveService 逻辑一致)
        var providers = all
            .Where(s => s.Enable && s.Healthy && s.Match(minVersion, scope, tags))
            .Select(s => s.ToModel())
            .ToList();

        var records = providers.Select(p => new
        {
            service_name = p.ServiceName,
            display_name = p.DisplayName,
            client = p.Client,
            version = p.Version,
            address = p.Address,
            external_address = p.Address2,
            scope = p.Scope,
            tag = p.Tag,
            weight = p.Weight,
            update_time = p.UpdateTime,
        }).ToList();

        return Task.FromResult<Object>(new
        {
            service_name = serviceName,
            scope,
            min_version = minVersion,
            tag,
            total = records.Count,
            records,
        });
    }
}