From ceb82cf36dfcc7559aceddbabe9bf3ab7e0fdc1b Mon Sep 17 00:00:00 2001 From: "Randall Castro - https://www.vauxoo.com" Date: Fri, 3 Apr 2026 22:14:19 -0600 Subject: [PATCH] feat: separate draft and direct send logic into distinct tools This commit addresses the maintainer's feedback by keeping the draft functionality under 'tg_draft' and introducing a new 'tg_send' tool that immediately sends the message. The README has been adjusted accordingly. --- .gitignore | 4 ++++ README.md | 3 ++- internal/tg/draft.go | 4 ++-- internal/tg/send.go | 48 ++++++++++++++++++++++++++++++++++++++++++++ serve.go | 7 ++++++- 5 files changed, 62 insertions(+), 4 deletions(-) create mode 100644 internal/tg/send.go diff --git a/.gitignore b/.gitignore index d73ad05..5f0b10e 100644 --- a/.gitignore +++ b/.gitignore @@ -73,3 +73,7 @@ bin/ log.txt mcp.log dist/ + +# Local binaries +telegram-mcp +telegram-mcp-out diff --git a/README.md b/README.md index 7e37c85..8686ac3 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,8 @@ The Model Context Protocol (MCP) is a system that lets AI apps, like Claude Desk - [x] List dialogs with optional unread filter (`tool: tg_dialogs`) - [x] Mark dialog as read (`tool: tg_read`) - [x] Retrieve messages from specific dialog (`tool: tg_dialog`) -- [x] Send draft messages to any dialog (`tool: tg_send`) +- [x] Send draft messages to any dialog (`tool: tg_draft`) +- [x] Send messages to any dialog immediately (`tool: tg_send`) ### Prompt examples diff --git a/internal/tg/draft.go b/internal/tg/draft.go index e934597..bd9ab00 100644 --- a/internal/tg/draft.go +++ b/internal/tg/draft.go @@ -35,12 +35,12 @@ func (c *Client) SendDraft(args DraftArguments) (*mcp.ToolResponse, error) { Message: args.Text, }) if err != nil { - return fmt.Errorf("failed to get history: %w", err) + return fmt.Errorf("save draft: %w", err) } return nil }); err != nil { - return nil, errors.Wrap(err, "failed to get history") + return nil, errors.Wrap(err, "failed to save draft") } jsonData, err := json.Marshal(DraftResponse{Success: ok}) diff --git a/internal/tg/send.go b/internal/tg/send.go new file mode 100644 index 0000000..dfda013 --- /dev/null +++ b/internal/tg/send.go @@ -0,0 +1,48 @@ +package tg + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/gotd/td/telegram/message" + mcp "github.com/metoro-io/mcp-golang" + "github.com/pkg/errors" +) + +type SendArguments struct { + Name string `json:"name" jsonschema:"required,description=Name of the dialog"` + Text string `json:"text" jsonschema:"required,description=Plain text of the message"` +} + +type SendResponse struct { + Success bool `json:"success"` +} + +func (c *Client) SendMessage(args SendArguments) (*mcp.ToolResponse, error) { + client := c.T() + if err := client.Run(context.Background(), func(ctx context.Context) (err error) { + api := client.API() + + inputPeer, err := getInputPeerFromName(ctx, api, args.Name) + if err != nil { + return fmt.Errorf("get inputPeer from name: %w", err) + } + + sender := message.NewSender(api) + if _, err = sender.To(inputPeer).Text(ctx, args.Text); err != nil { + return fmt.Errorf("send message: %w", err) + } + + return nil + }); err != nil { + return nil, errors.Wrap(err, "failed to send message") + } + + jsonData, err := json.Marshal(SendResponse{Success: true}) + if err != nil { + return nil, errors.Wrap(err, "failed to marshal response") + } + + return mcp.NewToolResponse(mcp.NewTextContent(string(jsonData))), nil +} diff --git a/serve.go b/serve.go index 7315655..22bd9d1 100644 --- a/serve.go +++ b/serve.go @@ -102,11 +102,16 @@ func serve(ctx context.Context, cmd *cli.Command) error { return fmt.Errorf("register dialogs tool: %w", err) } - err = server.RegisterTool("tg_send", "Send draft message to dialog", client.SendDraft) + err = server.RegisterTool("tg_draft", "Send draft message to dialog", client.SendDraft) if err != nil { return fmt.Errorf("register dialogs tool: %w", err) } + err = server.RegisterTool("tg_send", "Send message to dialog immediately", client.SendMessage) + if err != nil { + return fmt.Errorf("register send tool: %w", err) + } + err = server.RegisterTool("tg_read", "Mark dialog messages as read", client.ReadHistory) if err != nil { return fmt.Errorf("register read tool: %w", err)