mirror of
https://github.com/taigrr/gotify-mcp.git
synced 2025-10-23 01:27:18 +03:00
214 lines
5.7 KiB
Go
214 lines
5.7 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"log"
|
|
"net/http"
|
|
"os"
|
|
|
|
"github.com/modelcontextprotocol/go-sdk/mcp"
|
|
)
|
|
|
|
type GotifyMessage struct {
|
|
Message string `json:"message"`
|
|
Title string `json:"title,omitempty"`
|
|
Priority int `json:"priority,omitempty"`
|
|
}
|
|
|
|
type SendMessageArgs struct {
|
|
Message string `json:"message" jsonschema:"The message content to send"`
|
|
Title string `json:"title,omitempty" jsonschema:"Optional title for the message"`
|
|
Priority float64 `json:"priority,omitempty" jsonschema:"Message priority (0-10 default: 5)"`
|
|
}
|
|
|
|
type AskForHelpArgs struct {
|
|
Context string `json:"context" jsonschema:"Context or description of what help is needed"`
|
|
Error string `json:"error,omitempty" jsonschema:"Optional error message or details"`
|
|
}
|
|
|
|
type NotifyCompletionArgs struct {
|
|
Task string `json:"task" jsonschema:"Description of the completed task"`
|
|
Result string `json:"result,omitempty" jsonschema:"Optional result or outcome details"`
|
|
}
|
|
|
|
type SummarizeActivityArgs struct {
|
|
Summary string `json:"summary" jsonschema:"Summary of activities or current status"`
|
|
Details string `json:"details,omitempty" jsonschema:"Optional additional details"`
|
|
}
|
|
|
|
func main() {
|
|
server := mcp.NewServer(&mcp.Implementation{
|
|
Name: "Gotify Notification Server",
|
|
Version: "1.0.0",
|
|
}, nil)
|
|
|
|
mcp.AddTool(server, &mcp.Tool{
|
|
Name: "send-message",
|
|
Description: "Send a message to a Gotify server for notifications",
|
|
}, sendMessage)
|
|
|
|
mcp.AddTool(server, &mcp.Tool{
|
|
Name: "ask-for-help",
|
|
Description: "Send a help request notification to the user via Gotify",
|
|
}, askForHelp)
|
|
|
|
mcp.AddTool(server, &mcp.Tool{
|
|
Name: "notify-completion",
|
|
Description: "Send a completion notification to the user via Gotify",
|
|
}, notifyCompletion)
|
|
|
|
mcp.AddTool(server, &mcp.Tool{
|
|
Name: "summarize-activity",
|
|
Description: "Send a summary of current activities or status to the user via Gotify",
|
|
}, summarizeActivity)
|
|
|
|
if err := server.Run(context.Background(), &mcp.StdioTransport{}); err != nil {
|
|
log.Printf("Server error: %v\n", err)
|
|
}
|
|
}
|
|
|
|
func sendGotifyMessage(message GotifyMessage) error {
|
|
gotifyURL := os.Getenv("GOTIFY_URL")
|
|
gotifyToken := os.Getenv("GOTIFY_TOKEN")
|
|
|
|
if gotifyURL == "" {
|
|
return fmt.Errorf("GOTIFY_URL environment variable is not set")
|
|
}
|
|
if gotifyToken == "" {
|
|
return fmt.Errorf("GOTIFY_TOKEN environment variable is not set")
|
|
}
|
|
|
|
jsonData, err := json.Marshal(message)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to marshal message: %w", err)
|
|
}
|
|
|
|
url := fmt.Sprintf("%s/message?token=%s", gotifyURL, gotifyToken)
|
|
resp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonData))
|
|
if err != nil {
|
|
return fmt.Errorf("failed to send message: %w", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
return fmt.Errorf("gotify server returned status: %d", resp.StatusCode)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func sendMessage(ctx context.Context, req *mcp.CallToolRequest, args SendMessageArgs) (*mcp.CallToolResult, any, error) {
|
|
priority := 5
|
|
if args.Priority > 0 {
|
|
priority = int(args.Priority)
|
|
}
|
|
|
|
gotifyMsg := GotifyMessage{
|
|
Message: args.Message,
|
|
Title: args.Title,
|
|
Priority: priority,
|
|
}
|
|
|
|
if err := sendGotifyMessage(gotifyMsg); err != nil {
|
|
return &mcp.CallToolResult{
|
|
Content: []mcp.Content{
|
|
&mcp.TextContent{Text: fmt.Sprintf("Failed to send message: %s", err)},
|
|
},
|
|
IsError: true,
|
|
}, nil, nil
|
|
}
|
|
|
|
return &mcp.CallToolResult{
|
|
Content: []mcp.Content{
|
|
&mcp.TextContent{Text: "Message sent successfully"},
|
|
},
|
|
}, nil, nil
|
|
}
|
|
|
|
func askForHelp(ctx context.Context, req *mcp.CallToolRequest, args AskForHelpArgs) (*mcp.CallToolResult, any, error) {
|
|
message := fmt.Sprintf("🆘 Help needed: %s", args.Context)
|
|
if args.Error != "" {
|
|
message += fmt.Sprintf("\nError: %s", args.Error)
|
|
}
|
|
|
|
gotifyMsg := GotifyMessage{
|
|
Message: message,
|
|
Title: "Help Request",
|
|
Priority: 8,
|
|
}
|
|
|
|
if err := sendGotifyMessage(gotifyMsg); err != nil {
|
|
return &mcp.CallToolResult{
|
|
Content: []mcp.Content{
|
|
&mcp.TextContent{Text: fmt.Sprintf("Failed to send help request: %s", err)},
|
|
},
|
|
IsError: true,
|
|
}, nil, nil
|
|
}
|
|
|
|
return &mcp.CallToolResult{
|
|
Content: []mcp.Content{
|
|
&mcp.TextContent{Text: "Help request sent successfully"},
|
|
},
|
|
}, nil, nil
|
|
}
|
|
|
|
func notifyCompletion(ctx context.Context, req *mcp.CallToolRequest, args NotifyCompletionArgs) (*mcp.CallToolResult, any, error) {
|
|
message := fmt.Sprintf("✅ Task completed: %s", args.Task)
|
|
if args.Result != "" {
|
|
message += fmt.Sprintf("\nResult: %s", args.Result)
|
|
}
|
|
|
|
gotifyMsg := GotifyMessage{
|
|
Message: message,
|
|
Title: "Task Completed",
|
|
Priority: 6,
|
|
}
|
|
|
|
if err := sendGotifyMessage(gotifyMsg); err != nil {
|
|
return &mcp.CallToolResult{
|
|
Content: []mcp.Content{
|
|
&mcp.TextContent{Text: fmt.Sprintf("Failed to send completion notification: %s", err)},
|
|
},
|
|
IsError: true,
|
|
}, nil, nil
|
|
}
|
|
|
|
return &mcp.CallToolResult{
|
|
Content: []mcp.Content{
|
|
&mcp.TextContent{Text: "Completion notification sent successfully"},
|
|
},
|
|
}, nil, nil
|
|
}
|
|
|
|
func summarizeActivity(ctx context.Context, req *mcp.CallToolRequest, args SummarizeActivityArgs) (*mcp.CallToolResult, any, error) {
|
|
message := fmt.Sprintf("📊 Activity Summary: %s", args.Summary)
|
|
if args.Details != "" {
|
|
message += fmt.Sprintf("\nDetails: %s", args.Details)
|
|
}
|
|
|
|
gotifyMsg := GotifyMessage{
|
|
Message: message,
|
|
Title: "Activity Summary",
|
|
Priority: 4,
|
|
}
|
|
|
|
if err := sendGotifyMessage(gotifyMsg); err != nil {
|
|
return &mcp.CallToolResult{
|
|
Content: []mcp.Content{
|
|
&mcp.TextContent{Text: fmt.Sprintf("Failed to send summary: %s", err)},
|
|
},
|
|
IsError: true,
|
|
}, nil, nil
|
|
}
|
|
|
|
return &mcp.CallToolResult{
|
|
Content: []mcp.Content{
|
|
&mcp.TextContent{Text: "Activity summary sent successfully"},
|
|
},
|
|
}, nil, nil
|
|
}
|