You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
115 lines
2.8 KiB
115 lines
2.8 KiB
package mcp
|
|
|
|
import (
|
|
"context"
|
|
"yunyan/lego/core"
|
|
"yunyan/lego/core/cbase"
|
|
"yunyan/lego/sys/log"
|
|
"yunyan/sys/musicobj"
|
|
"yunyan/utils"
|
|
"fmt"
|
|
|
|
"github.com/mark3labs/mcp-go/mcp"
|
|
)
|
|
|
|
// 音乐工具(搜索+播放)
|
|
type tool_music struct {
|
|
cbase.ModuleCompBase
|
|
module *Mcp
|
|
}
|
|
|
|
// 组件初始化接口
|
|
func (this *tool_music) Init(service core.IService, module core.IModule, comp core.IModuleComp, opt core.IModuleOptions) (err error) {
|
|
this.ModuleCompBase.Init(service, module, comp, opt)
|
|
this.module = module.(*Mcp)
|
|
return
|
|
}
|
|
|
|
func (this *tool_music) Start() (err error) {
|
|
err = this.ModuleCompBase.Start()
|
|
if this.module.AddTool(ToolGroup_CHINA, this.Tool(), this.Handl) {
|
|
if err := musicobj.OnInit(this.module.service.GetSettings().Sys["musicobj"]); err != nil {
|
|
panic(fmt.Sprintf("init sys.musicobj err: %s", err.Error()))
|
|
} else {
|
|
log.Infof("init sys.musicobj success!")
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (this *tool_music) Tool() mcp.Tool {
|
|
return mcp.NewTool("music_search_play",
|
|
mcp.WithDescription("搜索音乐并返回带播放链接的音乐列表"),
|
|
mcp.WithString("query",
|
|
mcp.Description("搜索的音乐关键字 例如:小苹果, 周杰伦, 张学友, 流行音乐等"),
|
|
mcp.Required(),
|
|
mcp.DefaultString("热门"),
|
|
),
|
|
mcp.WithNumber("limit",
|
|
mcp.Description("返回结果数量 (1-20, default 10)"),
|
|
mcp.DefaultNumber(30),
|
|
),
|
|
mcp.WithNumber("offset",
|
|
mcp.Description("搜索的音乐偏移量 范围在0到9之间 (默认0)"),
|
|
mcp.DefaultNumber(0),
|
|
),
|
|
)
|
|
}
|
|
|
|
type MusicItem struct {
|
|
Id int64 `json:"id"`
|
|
Name string `json:"name"`
|
|
Singer string `json:"singer"`
|
|
Image string `json:"image"`
|
|
Url string `json:"url"`
|
|
}
|
|
|
|
func (this *tool_music) Handl(ctx context.Context, request mcp.CallToolRequest) (result *mcp.CallToolResult, err error) {
|
|
var (
|
|
query string
|
|
limit, offset int
|
|
songslist *musicobj.SearchResultResponse
|
|
)
|
|
if query, err = request.RequireString("query"); err != nil {
|
|
err = fmt.Errorf("query is required")
|
|
return
|
|
}
|
|
limit = request.GetInt("limit", 30)
|
|
offset = request.GetInt("offset", 0)
|
|
if songslist, err = musicobj.SearchMusic(query, limit, offset); err != nil {
|
|
this.module.Errorln(err)
|
|
return
|
|
}
|
|
if len(songslist.Data.Musics) == 0 {
|
|
err = fmt.Errorf("no music found")
|
|
return
|
|
}
|
|
|
|
musics := make([]*MusicItem, 0, len(songslist.Data.Musics))
|
|
for _, v := range songslist.Data.Musics {
|
|
item := &MusicItem{
|
|
Id: v.Id,
|
|
Name: v.Name,
|
|
Singer: v.Singer,
|
|
Image: v.Image,
|
|
}
|
|
if urlResp, urlErr := musicobj.MusicUrl(v.Id); urlErr == nil {
|
|
item.Url = urlResp.Data.URL
|
|
}
|
|
musics = append(musics, item)
|
|
}
|
|
|
|
text := utils.ToString(map[string]interface{}{
|
|
"data": musics,
|
|
"result": "success",
|
|
})
|
|
result = &mcp.CallToolResult{
|
|
Content: []mcp.Content{
|
|
mcp.TextContent{
|
|
Type: "text",
|
|
Text: text,
|
|
},
|
|
},
|
|
}
|
|
return
|
|
}
|
|
|