gui/pkg/mcp/tools_events.go
2026-04-15 14:14:32 +01:00

175 lines
5.5 KiB
Go

// pkg/mcp/tools_events.go
package mcp
import (
"context"
core "dappco.re/go/core"
coreerr "dappco.re/go/core/log"
"forge.lthn.ai/core/gui/pkg/events"
"github.com/modelcontextprotocol/go-sdk/mcp"
)
// --- event_emit ---
type EventEmitInput struct {
Name string `json:"name"`
Data any `json:"data,omitempty"`
}
type EventEmitOutput struct {
Cancelled bool `json:"cancelled"`
}
func (s *Subsystem) eventEmit(_ context.Context, _ *mcp.CallToolRequest, input EventEmitInput) (*mcp.CallToolResult, EventEmitOutput, error) {
r := s.core.Action("events.emit").Run(context.Background(), core.NewOptions(
core.Option{Key: "task", Value: events.TaskEmit{Name: input.Name, Data: input.Data}},
))
if !r.OK {
if e, ok := r.Value.(error); ok {
return nil, EventEmitOutput{}, e
}
return nil, EventEmitOutput{}, nil
}
cancelled, ok := r.Value.(bool)
if !ok {
return nil, EventEmitOutput{}, coreerr.E("mcp.eventEmit", "unexpected result type", nil)
}
return nil, EventEmitOutput{Cancelled: cancelled}, nil
}
// --- event_on ---
type EventOnInput struct {
Name string `json:"name"`
}
type EventOnOutput struct {
Success bool `json:"success"`
}
func (s *Subsystem) eventOn(_ context.Context, _ *mcp.CallToolRequest, input EventOnInput) (*mcp.CallToolResult, EventOnOutput, error) {
r := s.core.Action("events.on").Run(context.Background(), core.NewOptions(
core.Option{Key: "task", Value: events.TaskOn{Name: input.Name}},
))
if !r.OK {
if e, ok := r.Value.(error); ok {
return nil, EventOnOutput{}, e
}
return nil, EventOnOutput{}, nil
}
return nil, EventOnOutput{Success: true}, nil
}
// --- event_subscribe ---
type EventSubscribeInput struct {
Name string `json:"name"`
}
type EventSubscribeOutput struct {
Success bool `json:"success"`
}
func (s *Subsystem) eventSubscribe(ctx context.Context, req *mcp.CallToolRequest, input EventSubscribeInput) (*mcp.CallToolResult, EventSubscribeOutput, error) {
result, output, err := s.eventOn(ctx, req, EventOnInput{Name: input.Name})
if err != nil {
return nil, EventSubscribeOutput{}, err
}
if result != nil {
return result, EventSubscribeOutput{}, nil
}
return nil, EventSubscribeOutput{Success: output.Success}, nil
}
// --- event_off ---
type EventOffInput struct {
Name string `json:"name"`
}
type EventOffOutput struct {
Success bool `json:"success"`
}
func (s *Subsystem) eventOff(_ context.Context, _ *mcp.CallToolRequest, input EventOffInput) (*mcp.CallToolResult, EventOffOutput, error) {
r := s.core.Action("events.off").Run(context.Background(), core.NewOptions(
core.Option{Key: "task", Value: events.TaskOff{Name: input.Name}},
))
if !r.OK {
if e, ok := r.Value.(error); ok {
return nil, EventOffOutput{}, e
}
return nil, EventOffOutput{}, nil
}
return nil, EventOffOutput{Success: true}, nil
}
// --- event_unsubscribe ---
type EventUnsubscribeInput struct {
Name string `json:"name"`
}
type EventUnsubscribeOutput struct {
Success bool `json:"success"`
}
func (s *Subsystem) eventUnsubscribe(ctx context.Context, req *mcp.CallToolRequest, input EventUnsubscribeInput) (*mcp.CallToolResult, EventUnsubscribeOutput, error) {
result, output, err := s.eventOff(ctx, req, EventOffInput{Name: input.Name})
if err != nil {
return nil, EventUnsubscribeOutput{}, err
}
if result != nil {
return result, EventUnsubscribeOutput{}, nil
}
return nil, EventUnsubscribeOutput{Success: output.Success}, nil
}
// --- event_list ---
type EventListInput struct{}
type EventListOutput struct {
Listeners []events.ListenerInfo `json:"listeners"`
}
func (s *Subsystem) eventList(_ context.Context, _ *mcp.CallToolRequest, _ EventListInput) (*mcp.CallToolResult, EventListOutput, error) {
r := s.core.QUERY(events.QueryListeners{})
if !r.OK {
if e, ok := r.Value.(error); ok {
return nil, EventListOutput{}, e
}
return nil, EventListOutput{}, nil
}
listenerInfos, ok := r.Value.([]events.ListenerInfo)
if !ok {
return nil, EventListOutput{}, coreerr.E("mcp.eventList", "unexpected result type", nil)
}
return nil, EventListOutput{Listeners: listenerInfos}, nil
}
// --- event_info ---
type EventInfoInput struct{}
type EventInfoOutput struct {
Info events.ServerInfo `json:"info"`
}
func (s *Subsystem) eventInfo(_ context.Context, _ *mcp.CallToolRequest, _ EventInfoInput) (*mcp.CallToolResult, EventInfoOutput, error) {
r := s.core.QUERY(events.QueryServerInfo{})
if !r.OK {
return nil, EventInfoOutput{}, nil
}
info, ok := r.Value.(events.ServerInfo)
if !ok {
return nil, EventInfoOutput{}, coreerr.E("mcp.eventInfo", "unexpected result type", nil)
}
return nil, EventInfoOutput{Info: info}, nil
}
// --- Registration ---
func (s *Subsystem) registerEventsTools(server *mcp.Server) {
addTool(s, server, &mcp.Tool{Name: "event_emit", Description: "Fire a named custom event with optional data"}, s.eventEmit)
addTool(s, server, &mcp.Tool{Name: "event_on", Description: "Register a listener for a named custom event"}, s.eventOn)
addTool(s, server, &mcp.Tool{Name: "event_subscribe", Description: "Register a listener for a named custom event"}, s.eventSubscribe)
addTool(s, server, &mcp.Tool{Name: "event_off", Description: "Remove all listeners for a named custom event"}, s.eventOff)
addTool(s, server, &mcp.Tool{Name: "event_unsubscribe", Description: "Remove all listeners for a named custom event"}, s.eventUnsubscribe)
addTool(s, server, &mcp.Tool{Name: "event_list", Description: "Query all registered event listeners"}, s.eventList)
addTool(s, server, &mcp.Tool{Name: "event_info", Description: "Get WebSocket event server information"}, s.eventInfo)
}