Skip to main content
Glama
tools.ts8.15 kB
import { z } from 'zod'; import { zodToJsonSchema } from 'zod-to-json-schema'; import { GmailService } from './gmail-service.js'; const schemas = { search_emails: z.object({ query: z.string().describe("Gmail search query (e.g., 'is:unread', 'from:newsletter@example.com')"), maxResults: z.number().optional().default(10).describe("Maximum number of results (default: 10)") }), read_email: z.object({ messageId: z.string().describe("Email message ID") }), delete_email: z.object({ messageId: z.string().describe("Email message ID to delete") }), batch_delete_emails: z.object({ messageIds: z.array(z.string()).describe("Array of email message IDs to delete") }), list_labels: z.object({}), create_label: z.object({ name: z.string().describe("Label name") }), delete_label: z.object({ labelId: z.string().describe("Label ID to delete") }), apply_label: z.object({ messageId: z.string().describe("Email message ID"), labelId: z.string().describe("Label ID to apply") }), remove_label: z.object({ messageId: z.string().describe("Email message ID"), labelId: z.string().describe("Label ID to remove") }), batch_apply_labels: z.object({ messageIds: z.array(z.string()).describe("Array of email message IDs"), labelIds: z.array(z.string()).describe("Array of label IDs to apply") }), create_reply: z.object({ messageId: z.string().describe("Email message ID to reply to"), replyMessage: z.string().describe("The reply message content to create as a draft") }), authenticate_gmail: z.object({}) }; const toolDescriptions: Record<string, string> = { search_emails: "Search emails using Gmail query syntax", read_email: "Read the full content of an email", delete_email: "Permanently delete an email", batch_delete_emails: "Delete multiple emails at once", list_labels: "List all Gmail labels", create_label: "Create a new Gmail label", delete_label: "Delete a Gmail label", apply_label: "Apply a label to an email", remove_label: "Remove a label from an email", batch_apply_labels: "Apply labels to multiple emails at once", create_reply: "Generate a brief, natural reply draft and provide Gmail compose URL", authenticate_gmail: "Authenticate Gmail access via web browser (opens browser automatically)" }; export const getToolDefinitions = () => Object.entries(schemas).map(([name, schema]) => ({ name, description: toolDescriptions[name], inputSchema: zodToJsonSchema(schema) })); export async function handleToolCall(gmailService: GmailService, name: string, args: any) { try { const schema = schemas[name as keyof typeof schemas]; if (!schema) throw new Error(`Unknown tool: ${name}`); const validated = schema.parse(args); switch (name) { case "search_emails": { const v = validated as z.infer<typeof schemas.search_emails>; const results = await gmailService.searchEmails(v.query, v.maxResults); return { content: [{ type: "text", text: results.length ? results.map(e => `ID: ${e.id}\nSubject: ${e.subject}\nFrom: ${e.from}\nDate: ${e.date}\nSnippet: ${e.snippet}\nGmail URL: ${gmailService.getEmailUrl(e.id)}\n`).join('---\n') : "No emails found." }] }; } case "read_email": { const v = validated as z.infer<typeof schemas.read_email>; const email = await gmailService.readEmail(v.messageId); return { content: [{ type: "text", text: `Subject: ${email.subject}\nFrom: ${email.from}\nTo: ${email.to}\nDate: ${email.date}\nThread ID: ${email.threadId}\nGmail URL: ${gmailService.getEmailUrl(v.messageId)}\n\nContent:\n${email.body}` }] }; } case "delete_email": { const v = validated as z.infer<typeof schemas.delete_email>; await gmailService.deleteEmail(v.messageId); return { content: [{ type: "text", text: `Email ${v.messageId} deleted successfully.` }] }; } case "batch_delete_emails": { const v = validated as z.infer<typeof schemas.batch_delete_emails>; const result = await gmailService.batchDeleteEmails(v.messageIds); return { content: [{ type: "text", text: `Batch delete completed:\nSuccessfully deleted: ${result.successes} emails\nFailed: ${result.failures} emails` }] }; } case "list_labels": { const labels = await gmailService.listLabels(); const system = labels.filter(l => l.type === 'system'); const user = labels.filter(l => l.type === 'user'); return { content: [{ type: "text", text: labels.length ? `System Labels (${system.length}):\n${system.map(l => ` - ${l.name} (${l.id})`).join('\n')}\n\nUser Labels (${user.length}):\n${user.map(l => ` - ${l.name} (${l.id})`).join('\n')}` : "No labels found." }] }; } case "create_label": { const v = validated as z.infer<typeof schemas.create_label>; const label = await gmailService.createLabel(v.name); return { content: [{ type: "text", text: `Label created successfully:\nName: ${label.name}\nID: ${label.id}` }] }; } case "delete_label": { const v = validated as z.infer<typeof schemas.delete_label>; await gmailService.deleteLabel(v.labelId); return { content: [{ type: "text", text: `Label ${v.labelId} deleted successfully.` }] }; } case "apply_label": { const v = validated as z.infer<typeof schemas.apply_label>; await gmailService.applyLabel(v.messageId, v.labelId); return { content: [{ type: "text", text: `Label ${v.labelId} applied to email ${v.messageId}.` }] }; } case "remove_label": { const v = validated as z.infer<typeof schemas.remove_label>; await gmailService.removeLabel(v.messageId, v.labelId); return { content: [{ type: "text", text: `Label ${v.labelId} removed from email ${v.messageId}.` }] }; } case "batch_apply_labels": { const v = validated as z.infer<typeof schemas.batch_apply_labels>; const result = await gmailService.batchApplyLabels(v.messageIds, v.labelIds); return { content: [{ type: "text", text: `Batch label application completed:\nSuccessfully processed: ${result.successes} emails\nFailed: ${result.failures} emails` }] }; } case "create_reply": { const v = validated as z.infer<typeof schemas.create_reply>; const result = await gmailService.createReply(v.messageId, v.replyMessage); return { content: [{ type: "text", text: `${result.message}\n\n**Draft Preview:**\n\n**To:** ${result.to}\n**Subject:** ${result.subject}\n\n**Message:**\n\`\`\`\n${result.replyMessage}\n\`\`\`` }] }; } case "authenticate_gmail": { // This is a special case - handled in index.ts throw new Error("Authentication should be handled by the main server"); } default: throw new Error(`Unknown tool: ${name}`); } } catch (error: any) { return { content: [{ type: "text", text: `Error: ${error.message}` }] }; } }

Implementation Reference

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/muammar-yacoob/GMail-Manager-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server