Ctrl K
ComunidadGuías…

internal/mcptools/get_channels.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package mcptools

import (
	"context"
	"errors"
	"log"
	"strings"

	"xprem/internal/types"

	mcpprot "github.com/modelcontextprotocol/go-sdk/mcp"
)

type GetChannelsInput struct {
	AppId string `json:"appId" jsonschema:"the app id, as returned by get_apps"`
	Name  string `json:"name,omitempty" jsonschema:"exact channel name, to fetch a single channel"`
	Id    string `json:"id,omitempty" jsonschema:"exact channel id, to fetch a single channel"`
}

// matchesChannel applies the optional name/id narrowing.
func matchesChannel(channel types.ChannelMapping, name string, id string) bool {
	if name != "" && !strings.EqualFold(channel.ReleaseChannelName, name) {
		return false
	}
	if id != "" && channel.ReleaseChannelId != id {
		return false
	}
	return true
}

type GetChannelsOutput struct {
	Channels []types.ChannelMapping `json:"channels"`
}

func getChannelsHandler(deps Deps) func(ctx context.Context, req *mcpprot.CallToolRequest, input GetChannelsInput) (*mcpprot.CallToolResult, GetChannelsOutput, error) {
	return func(ctx context.Context, req *mcpprot.CallToolRequest, input GetChannelsInput) (*mcpprot.CallToolResult, GetChannelsOutput, error) {
		principal := PrincipalFromRequest(req)
		if principal == nil {
			return nil, GetChannelsOutput{}, errors.New("no authenticated account on this session")
		}
		if err := requireAppVisible(ctx, deps, principal, input.AppId); err != nil {
			return nil, GetChannelsOutput{}, err
		}
		channels, err := deps.Channels.GetChannels(ctx, input.AppId)
		if err != nil {
			log.Printf("mcp get_channels failed for app %s: %v", input.AppId, err)
			return nil, GetChannelsOutput{}, errors.New("could not list the channels, try again later")
		}
		output := GetChannelsOutput{Channels: []types.ChannelMapping{}}
		for _, channel := range channels {
			if !matchesChannel(channel, input.Name, input.Id) {
				continue
			}
			output.Channels = append(output.Channels, channel)
		}
		return nil, output, nil
	}
}

func registerGetChannels(server *mcpprot.Server, deps Deps) {
	mcpprot.AddTool(server, &mcpprot.Tool{
		Name:        "get_channels",
		Description: "The release channels of an app (appId required, from get_apps), with their linked branch, current updates, and the active progressive rollout if any. Pass name or id to fetch a single channel.",
		Annotations: &mcpprot.ToolAnnotations{Title: "List channels", ReadOnlyHint: true},
	}, getChannelsHandler(deps))
}

type ChannelRolloutOutput struct {
	ChannelName string               `json:"channelName"`
	Rollout     types.ChannelRollout `json:"rollout"`
}

type GetChannelRolloutsOutput struct {
	Rollouts []ChannelRolloutOutput `json:"rollouts"`
}

func getChannelRolloutsHandler(deps Deps) func(ctx context.Context, req *mcpprot.CallToolRequest, input GetChannelsInput) (*mcpprot.CallToolResult, GetChannelRolloutsOutput, error) {
	return func(ctx context.Context, req *mcpprot.CallToolRequest, input GetChannelsInput) (*mcpprot.CallToolResult, GetChannelRolloutsOutput, error) {
		principal := PrincipalFromRequest(req)
		if principal == nil {
			return nil, GetChannelRolloutsOutput{}, errors.New("no authenticated account on this session")
		}
		if err := requireAppVisible(ctx, deps, principal, input.AppId); err != nil {
			return nil, GetChannelRolloutsOutput{}, err
		}
		channels, err := deps.Channels.GetChannels(ctx, input.AppId)
		if err != nil {
			log.Printf("mcp get_channel_rollouts failed for app %s: %v", input.AppId, err)
			return nil, GetChannelRolloutsOutput{}, errors.New("could not list the channel rollouts, try again later")
		}
		output := GetChannelRolloutsOutput{Rollouts: []ChannelRolloutOutput{}}
		for _, channel := range channels {
			if channel.Rollout == nil {
				continue
			}
			if !matchesChannel(channel, input.Name, input.Id) {
				continue
			}
			output.Rollouts = append(output.Rollouts, ChannelRolloutOutput{
				ChannelName: channel.ReleaseChannelName,
				Rollout:     *channel.Rollout,
			})
		}
		return nil, output, nil
	}
}

func registerGetChannelRollouts(server *mcpprot.Server, deps Deps) {
	mcpprot.AddTool(server, &mcpprot.Tool{
		Name:        "get_channel_rollouts",
		Description: "The active progressive rollouts between branches on the channels of an app (appId required). An empty list means no channel rollout is in progress. Pass name or id to check a single channel.",
		Annotations: &mcpprot.ToolAnnotations{Title: "Channel rollouts", ReadOnlyHint: true},
	}, getChannelRolloutsHandler(deps))
}