Commit f847fd0
Changed files (1)
pkg
imap
pkg/imap/server.go
@@ -75,18 +75,7 @@ func NewServer(server, username, password string, port int, useTLS bool) *Server
useTLS: useTLS,
}
- s.RegisterTool("imap_list_folders", s.handleListFolders)
- s.RegisterTool("imap_list_messages", s.handleListMessages)
- s.RegisterTool("imap_read_message", s.handleReadMessage)
- s.RegisterTool("imap_search_messages", s.handleSearchMessages)
- s.RegisterTool("imap_get_folder_stats", s.handleGetFolderStats)
- s.RegisterTool("imap_mark_as_read", s.handleMarkAsRead)
- s.RegisterTool("imap_get_attachments", s.handleGetAttachments)
- s.RegisterTool("imap_get_connection_info", s.handleGetConnectionInfo)
- s.RegisterTool("imap_delete_message", s.handleDeleteMessage)
- s.RegisterTool("imap_delete_messages", s.handleDeleteMessages)
- s.RegisterTool("imap_move_to_trash", s.handleMoveToTrash)
- s.RegisterTool("imap_expunge_folder", s.handleExpungeFolder)
+ s.registerTools()
// Register prompts
analysisPrompt := mcp.Prompt{
@@ -103,6 +92,307 @@ func NewServer(server, username, password string, port int, useTLS bool) *Server
return s
}
+// ListTools returns all available IMAP email management tools
+func (s *Server) ListTools() []mcp.Tool {
+ return []mcp.Tool{
+ {
+ Name: "imap_list_folders",
+ Description: "List all folders in the email account (INBOX, Sent, Drafts, etc.)",
+ InputSchema: map[string]interface{}{
+ "type": "object",
+ "properties": map[string]interface{}{},
+ },
+ },
+ {
+ Name: "imap_list_messages",
+ Description: "List messages in a folder with optional pagination and filtering",
+ InputSchema: map[string]interface{}{
+ "type": "object",
+ "properties": map[string]interface{}{
+ "folder": map[string]interface{}{
+ "type": "string",
+ "description": "Folder name (default: INBOX)",
+ },
+ "limit": map[string]interface{}{
+ "type": "integer",
+ "description": "Maximum number of messages to return (default: 20)",
+ "minimum": 1,
+ "maximum": 100,
+ },
+ "offset": map[string]interface{}{
+ "type": "integer",
+ "description": "Number of messages to skip (for pagination) (default: 0)",
+ "minimum": 0,
+ },
+ "unread_only": map[string]interface{}{
+ "type": "boolean",
+ "description": "Show only unread messages (default: false)",
+ },
+ },
+ },
+ },
+ {
+ Name: "imap_read_message",
+ Description: "Read the full content of a specific email message",
+ InputSchema: map[string]interface{}{
+ "type": "object",
+ "properties": map[string]interface{}{
+ "uid": map[string]interface{}{
+ "type": "integer",
+ "description": "Message UID",
+ },
+ "folder": map[string]interface{}{
+ "type": "string",
+ "description": "Folder name (default: INBOX)",
+ },
+ "mark_as_read": map[string]interface{}{
+ "type": "boolean",
+ "description": "Mark message as read when reading (default: false)",
+ },
+ },
+ "required": []string{"uid"},
+ },
+ },
+ {
+ Name: "imap_search_messages",
+ Description: "Search for messages by content, sender, subject, or other criteria",
+ InputSchema: map[string]interface{}{
+ "type": "object",
+ "properties": map[string]interface{}{
+ "query": map[string]interface{}{
+ "type": "string",
+ "description": "Search query text",
+ },
+ "folder": map[string]interface{}{
+ "type": "string",
+ "description": "Folder to search in (default: INBOX)",
+ },
+ "search_type": map[string]interface{}{
+ "type": "string",
+ "description": "Type of search (subject, from, body, all) (default: all)",
+ "enum": []string{"subject", "from", "to", "body", "all"},
+ },
+ "since_date": map[string]interface{}{
+ "type": "string",
+ "description": "Search messages since this date (YYYY-MM-DD format)",
+ },
+ "before_date": map[string]interface{}{
+ "type": "string",
+ "description": "Search messages before this date (YYYY-MM-DD format)",
+ },
+ "limit": map[string]interface{}{
+ "type": "integer",
+ "description": "Maximum number of results (default: 50)",
+ "minimum": 1,
+ "maximum": 200,
+ },
+ },
+ "required": []string{"query"},
+ },
+ },
+ {
+ Name: "imap_get_folder_stats",
+ Description: "Get statistics for a folder (total messages, unread count, etc.)",
+ InputSchema: map[string]interface{}{
+ "type": "object",
+ "properties": map[string]interface{}{
+ "folder": map[string]interface{}{
+ "type": "string",
+ "description": "Folder name (default: INBOX)",
+ },
+ },
+ },
+ },
+ {
+ Name: "imap_mark_as_read",
+ Description: "Mark one or more messages as read or unread",
+ InputSchema: map[string]interface{}{
+ "type": "object",
+ "properties": map[string]interface{}{
+ "uid": map[string]interface{}{
+ "type": "integer",
+ "description": "Message UID to mark",
+ },
+ "uids": map[string]interface{}{
+ "type": "array",
+ "items": map[string]interface{}{
+ "type": "integer",
+ },
+ "description": "Array of message UIDs to mark (alternative to single uid)",
+ },
+ "folder": map[string]interface{}{
+ "type": "string",
+ "description": "Folder name (default: INBOX)",
+ },
+ "read": map[string]interface{}{
+ "type": "boolean",
+ "description": "Mark as read (true) or unread (false) (default: true)",
+ },
+ },
+ },
+ },
+ {
+ Name: "imap_get_attachments",
+ Description: "List attachments for a message",
+ InputSchema: map[string]interface{}{
+ "type": "object",
+ "properties": map[string]interface{}{
+ "uid": map[string]interface{}{
+ "type": "integer",
+ "description": "Message UID",
+ },
+ "folder": map[string]interface{}{
+ "type": "string",
+ "description": "Folder name (default: INBOX)",
+ },
+ },
+ "required": []string{"uid"},
+ },
+ },
+ {
+ Name: "imap_get_connection_info",
+ Description: "Get information about the IMAP server connection and capabilities",
+ InputSchema: map[string]interface{}{
+ "type": "object",
+ "properties": map[string]interface{}{},
+ },
+ },
+ {
+ Name: "imap_delete_message",
+ Description: "Delete a single message (requires confirmation for safety)",
+ InputSchema: map[string]interface{}{
+ "type": "object",
+ "properties": map[string]interface{}{
+ "uid": map[string]interface{}{
+ "type": "integer",
+ "description": "Message UID to delete",
+ },
+ "folder": map[string]interface{}{
+ "type": "string",
+ "description": "Folder name (default: INBOX)",
+ },
+ "confirmed": map[string]interface{}{
+ "type": "boolean",
+ "description": "Confirmation that you want to permanently delete this message",
+ },
+ },
+ "required": []string{"uid", "confirmed"},
+ },
+ },
+ {
+ Name: "imap_delete_messages",
+ Description: "Delete multiple messages in bulk (requires confirmation for safety)",
+ InputSchema: map[string]interface{}{
+ "type": "object",
+ "properties": map[string]interface{}{
+ "uids": map[string]interface{}{
+ "type": "array",
+ "items": map[string]interface{}{
+ "type": "integer",
+ },
+ "description": "Array of message UIDs to delete",
+ },
+ "folder": map[string]interface{}{
+ "type": "string",
+ "description": "Folder name (default: INBOX)",
+ },
+ "confirmed": map[string]interface{}{
+ "type": "boolean",
+ "description": "Confirmation that you want to permanently delete these messages",
+ },
+ },
+ "required": []string{"uids", "confirmed"},
+ },
+ },
+ {
+ Name: "imap_move_to_trash",
+ Description: "Move messages to trash folder (safer alternative to permanent deletion)",
+ InputSchema: map[string]interface{}{
+ "type": "object",
+ "properties": map[string]interface{}{
+ "uid": map[string]interface{}{
+ "type": "integer",
+ "description": "Message UID to move to trash",
+ },
+ "uids": map[string]interface{}{
+ "type": "array",
+ "items": map[string]interface{}{
+ "type": "integer",
+ },
+ "description": "Array of message UIDs to move to trash (alternative to single uid)",
+ },
+ "folder": map[string]interface{}{
+ "type": "string",
+ "description": "Source folder name (default: INBOX)",
+ },
+ "trash_folder": map[string]interface{}{
+ "type": "string",
+ "description": "Trash folder name (default: Trash or [Gmail]/Trash)",
+ },
+ },
+ },
+ },
+ {
+ Name: "imap_expunge_folder",
+ Description: "Permanently remove messages marked for deletion from a folder",
+ InputSchema: map[string]interface{}{
+ "type": "object",
+ "properties": map[string]interface{}{
+ "folder": map[string]interface{}{
+ "type": "string",
+ "description": "Folder name to expunge (default: INBOX)",
+ },
+ "confirmed": map[string]interface{}{
+ "type": "boolean",
+ "description": "Confirmation that you want to permanently expunge deleted messages",
+ },
+ },
+ "required": []string{"confirmed"},
+ },
+ },
+ }
+}
+
+// registerTools registers all IMAP tools with the server
+func (s *Server) registerTools() {
+ // Get all tool definitions from ListTools method
+ tools := s.ListTools()
+
+ // Register each tool with its proper definition
+ for _, tool := range tools {
+ var handler mcp.ToolHandler
+ switch tool.Name {
+ case "imap_list_folders":
+ handler = s.handleListFolders
+ case "imap_list_messages":
+ handler = s.handleListMessages
+ case "imap_read_message":
+ handler = s.handleReadMessage
+ case "imap_search_messages":
+ handler = s.handleSearchMessages
+ case "imap_get_folder_stats":
+ handler = s.handleGetFolderStats
+ case "imap_mark_as_read":
+ handler = s.handleMarkAsRead
+ case "imap_get_attachments":
+ handler = s.handleGetAttachments
+ case "imap_get_connection_info":
+ handler = s.handleGetConnectionInfo
+ case "imap_delete_message":
+ handler = s.handleDeleteMessage
+ case "imap_delete_messages":
+ handler = s.handleDeleteMessages
+ case "imap_move_to_trash":
+ handler = s.handleMoveToTrash
+ case "imap_expunge_folder":
+ handler = s.handleExpungeFolder
+ default:
+ continue
+ }
+ s.RegisterToolWithDefinition(tool, handler)
+ }
+}
+
func (s *Server) connect() error {
if s.connected && s.client != nil {
return nil