← back to George Mcp
add gmail_send_attachment tool: send email with local-file attachments via /api/send-with-attachment
d9bbb802de4ba5a43f3ca8d9db93480c6d960171 · 2026-07-10 11:22:13 -0700 · Steve Abrams
Files touched
Diff
commit d9bbb802de4ba5a43f3ca8d9db93480c6d960171
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Fri Jul 10 11:22:13 2026 -0700
add gmail_send_attachment tool: send email with local-file attachments via /api/send-with-attachment
---
index.js | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 55 insertions(+)
diff --git a/index.js b/index.js
index 54a051b..88ea4d3 100755
--- a/index.js
+++ b/index.js
@@ -220,6 +220,29 @@ const TOOLS = [
additionalProperties: false,
},
},
+ {
+ name: "gmail_send_attachment",
+ description:
+ "Send an email WITH one or more file attachments from a DW Gmail account (steve-office / steve@designerwallcoverings.com by default — pass account:'info' to send from info@). Body is HTML. `attachments` are LOCAL filesystem paths — the bridge reads each file, base64-encodes it, and posts to George's /api/send-with-attachment. Use this instead of gmail_send whenever a file must be attached.",
+ inputSchema: {
+ type: "object",
+ properties: {
+ to: { type: "string" },
+ subject: { type: "string" },
+ body: { type: "string", description: "HTML body" },
+ cc: { type: "string" },
+ bcc: { type: "string" },
+ attachments: {
+ type: "array",
+ description: "Local filesystem paths to attach.",
+ items: { type: "string" },
+ },
+ ...ACCOUNT_PROP,
+ },
+ required: ["to", "subject", "body", "attachments"],
+ additionalProperties: false,
+ },
+ },
{
name: "gmail_create_draft",
description: "Create a Gmail draft instead of sending immediately.",
@@ -316,6 +339,38 @@ server.setRequestHandler(CallToolRequestSchema, async (req) => {
case "gmail_send":
data = await george("/api/send", { method: "POST", body: args });
break;
+ case "gmail_send_attachment": {
+ const fs = await import("node:fs");
+ const path = await import("node:path");
+ const MIME = {
+ ".pdf": "application/pdf",
+ ".doc": "application/msword",
+ ".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
+ ".xls": "application/vnd.ms-excel",
+ ".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
+ ".png": "image/png",
+ ".jpg": "image/jpeg",
+ ".jpeg": "image/jpeg",
+ ".gif": "image/gif",
+ ".txt": "text/plain",
+ ".csv": "text/csv",
+ ".zip": "application/zip",
+ };
+ const paths = Array.isArray(args.attachments) ? args.attachments : [args.attachments];
+ const attachments = paths.filter(Boolean).map((p) => {
+ const ext = path.extname(String(p)).toLowerCase();
+ return {
+ filename: path.basename(String(p)),
+ content_base64: fs.readFileSync(String(p)).toString("base64"),
+ mime_type: MIME[ext] || "application/octet-stream",
+ };
+ });
+ data = await george("/api/send-with-attachment", {
+ method: "POST",
+ body: { to: args.to, cc: args.cc, bcc: args.bcc, subject: args.subject, body: args.body, account, attachments },
+ });
+ break;
+ }
case "gmail_create_draft":
data = await george("/api/drafts", { method: "POST", body: args });
break;
← b2cbb3d fix gmail_get_attachment: fetch raw bytes + save locally (re
·
back to George Mcp
·
chore: lint, refactor, v0.2.0 (session close) 67b3cb6 →