Code Snippet Server
by ngeojiajun
Verified
- src
- handlers
import { GmailService } from "../services/gmail-service.js";
import { CalendarService } from "../services/calendar-service.js";
import {
CallToolRequest,
CallToolResult,
ListToolsRequest,
ListToolsResult,
Tool,
} from "@modelcontextprotocol/sdk/types.js";
import type {
SendEmailOptions,
DraftEmailOptions,
} from "../services/gmail-service.js";
import { SystemPromptService } from "../services/systemprompt-service.js";
interface ListMessagesArgs {
maxResults?: number;
after?: string; // Date in YYYY/MM/DD format
before?: string; // Date in YYYY/MM/DD format
sender?: string; // Sender email address
to?: string; // Recipient email address
subject?: string; // Subject line text
hasAttachment?: boolean; // Whether the email has attachments
label?: string; // Gmail label name
_message: string; // A placeholder message to ensure properties are never empty.
}
interface GetMessageArgs {
messageId: string;
_message: string; // A placeholder message to ensure properties are never empty.
}
interface SearchMessagesArgs {
query: string;
maxResults?: number;
after?: string; // Date in YYYY/MM/DD format
before?: string; // Date in YYYY/MM/DD format
_message: string; // A placeholder message to ensure properties are never empty.
}
interface ListEventsArgs {
calendarId?: string;
maxResults?: number;
_message: string; // A placeholder message to ensure properties are never empty.
}
interface GetEventArgs {
eventId: string;
calendarId?: string;
_message: string; // A placeholder message to ensure properties are never empty.
}
interface SearchEventsArgs {
query: string;
calendarId?: string;
maxResults?: number;
_message: string; // A placeholder message to ensure properties are never empty.
}
const TOOLS: Tool[] = [
{
name: "systemprompt_list_messages",
description:
"Lists recent Gmail messages from the user's inbox with optional filtering.",
inputSchema: {
type: "object" as const,
properties: {
maxResults: {
type: "number" as const,
description: "Maximum number of messages to return. Defaults to 10.",
},
after: {
type: "string" as const,
description: "Return messages after this date (format: YYYY/MM/DD).",
},
before: {
type: "string" as const,
description: "Return messages before this date (format: YYYY/MM/DD).",
},
sender: {
type: "string" as const,
description: "Filter messages from this sender email address.",
},
to: {
type: "string" as const,
description: "Filter messages sent to this recipient email address.",
},
subject: {
type: "string" as const,
description:
"Filter messages containing this text in the subject line.",
},
hasAttachment: {
type: "boolean" as const,
description: "Filter messages that have attachments.",
},
label: {
type: "string" as const,
description: "Filter messages with this Gmail label.",
},
},
},
},
{
name: "systemprompt_get_message",
description:
"Retrieves the full content of a specific Gmail message by its ID.",
inputSchema: {
type: "object" as const,
properties: {
messageId: {
type: "string" as const,
description: "The ID of the Gmail message to retrieve.",
},
},
},
},
{
name: "systemprompt_search_messages",
description: "Searches Gmail messages using Gmail's search syntax.",
inputSchema: {
type: "object" as const,
properties: {
query: {
type: "string" as const,
description: "Gmail search query string.",
},
maxResults: {
type: "number" as const,
description: "Maximum number of messages to return. Defaults to 10.",
},
after: {
type: "string" as const,
description: "Return messages after this date (format: YYYY/MM/DD).",
},
before: {
type: "string" as const,
description: "Return messages before this date (format: YYYY/MM/DD).",
},
},
required: ["query"],
},
},
{
name: "systemprompt_list_labels",
description: "Lists all Gmail labels in the user's account.",
inputSchema: {
type: "object" as const,
properties: {
_message: {
type: "string" as const,
description:
"A placeholder message to ensure properties are never empty.",
},
},
},
},
{
name: "systemprompt_list_events",
description: "Lists upcoming events from the user's Google Calendar.",
inputSchema: {
type: "object" as const,
properties: {
calendarId: {
type: "string" as const,
description:
"ID of the calendar to fetch events from. Defaults to primary calendar.",
},
maxResults: {
type: "number" as const,
description: "Maximum number of events to return. Defaults to 10.",
},
},
},
},
{
name: "systemprompt_get_event",
description: "Retrieves details of a specific calendar event by its ID.",
inputSchema: {
type: "object" as const,
properties: {
eventId: {
type: "string" as const,
description: "The ID of the calendar event to retrieve.",
},
calendarId: {
type: "string" as const,
description:
"ID of the calendar containing the event. Defaults to primary calendar.",
},
},
required: ["eventId"],
},
},
{
name: "systemprompt_search_events",
description: "Searches for calendar events using free text search.",
inputSchema: {
type: "object" as const,
properties: {
query: {
type: "string" as const,
description: "Search query string for finding events.",
},
calendarId: {
type: "string" as const,
description:
"ID of the calendar to search in. Defaults to primary calendar.",
},
maxResults: {
type: "number" as const,
description: "Maximum number of events to return. Defaults to 10.",
},
},
required: ["query"],
},
},
{
name: "systemprompt_list_calendars",
description:
"Lists all calendars available in the user's Google Calendar account.",
inputSchema: {
type: "object" as const,
properties: {
_message: {
type: "string" as const,
description:
"A placeholder message to ensure properties are never empty.",
},
},
},
},
{
name: "systemprompt_send_email",
description:
"Sends an email with optional attachments, CC, and BCC recipients.",
inputSchema: {
type: "object" as const,
properties: {
to: {
type: "string" as const,
description:
"Recipient email address(es). Multiple addresses can be comma-separated.",
},
subject: {
type: "string" as const,
description: "Email subject line.",
},
body: {
type: "string" as const,
description: "Email body content. Can be plain text or HTML.",
},
cc: {
type: "string" as const,
description:
"CC recipient email address(es). Multiple addresses can be comma-separated.",
},
bcc: {
type: "string" as const,
description:
"BCC recipient email address(es). Multiple addresses can be comma-separated.",
},
isHtml: {
type: "boolean" as const,
description:
"Whether the body content is HTML. Defaults to false for plain text.",
},
},
required: ["to", "subject", "body"],
},
},
{
name: "systemprompt_create_draft",
description: "Creates a draft email that can be edited and sent later.",
inputSchema: {
type: "object" as const,
properties: {
to: {
type: "string" as const,
description:
"Recipient email address(es). Multiple addresses can be comma-separated.",
},
subject: {
type: "string" as const,
description: "Email subject line.",
},
body: {
type: "string" as const,
description: "Email body content. Can be plain text or HTML.",
},
cc: {
type: "string" as const,
description:
"CC recipient email address(es). Multiple addresses can be comma-separated.",
},
bcc: {
type: "string" as const,
description:
"BCC recipient email address(es). Multiple addresses can be comma-separated.",
},
isHtml: {
type: "boolean" as const,
description:
"Whether the body content is HTML. Defaults to false for plain text.",
},
},
required: ["to", "subject", "body"],
},
},
{
name: "systemprompt_list_drafts",
description: "Lists all draft emails in the user's account.",
inputSchema: {
type: "object" as const,
properties: {
maxResults: {
type: "number" as const,
description: "Maximum number of drafts to return. Defaults to 10.",
},
},
},
},
{
name: "systemprompt_delete_draft",
description: "Deletes a draft email by its ID.",
inputSchema: {
type: "object" as const,
properties: {
draftId: {
type: "string" as const,
description: "The ID of the draft to delete.",
},
_message: {
type: "string" as const,
description:
"A placeholder message to ensure properties are never empty.",
},
},
required: ["draftId"],
},
},
];
export async function handleListTools(
request: ListToolsRequest
): Promise<ListToolsResult> {
return { tools: TOOLS };
}
export async function handleToolCall(
request: CallToolRequest
): Promise<CallToolResult> {
try {
switch (request.params.name) {
// Gmail Tools
case "systemprompt_list_messages": {
const gmail = new GmailService();
const args = request.params.arguments as unknown as ListMessagesArgs;
// Build Gmail search query from filters
let searchQuery = "";
if (args.after)
searchQuery += ` after:${args.after.replace(/-/g, "/")}`;
if (args.before)
searchQuery += ` before:${args.before.replace(/-/g, "/")}`;
if (args.sender) searchQuery += ` from:${args.sender}`;
if (args.to) searchQuery += ` to:${args.to}`;
if (args.subject) searchQuery += ` subject:${args.subject}`;
if (args.hasAttachment) searchQuery += " has:attachment";
if (args.label) searchQuery += ` label:${args.label}`;
// If there are filters, use search instead of list
const messages = searchQuery.trim()
? await gmail.searchMessages(searchQuery.trim(), args.maxResults)
: await gmail.listMessages(args.maxResults);
return {
content: [
{
type: "text",
text: JSON.stringify(messages, null, 2),
},
],
};
}
case "systemprompt_get_message": {
const gmail = new GmailService();
const args = request.params.arguments as unknown as GetMessageArgs;
const message = await gmail.getMessage(args.messageId);
return {
content: [
{
type: "text",
text: JSON.stringify(message, null, 2),
},
],
};
}
case "systemprompt_search_messages": {
const gmail = new GmailService();
const args = request.params.arguments as unknown as SearchMessagesArgs;
// Append date filters to search query if provided
let searchQuery = args.query;
if (args.after)
searchQuery += ` after:${args.after.replace(/-/g, "/")}`;
if (args.before)
searchQuery += ` before:${args.before.replace(/-/g, "/")}`;
const messages = await gmail.searchMessages(
searchQuery,
args.maxResults
);
return {
content: [
{
type: "text",
text: JSON.stringify(messages, null, 2),
},
],
};
}
case "systemprompt_list_labels": {
const gmail = new GmailService();
const labels = await gmail.getLabels();
return {
content: [
{
type: "text",
text: JSON.stringify(labels, null, 2),
},
],
};
}
// Calendar Tools
case "systemprompt_list_events": {
const calendar = new CalendarService();
const args = request.params.arguments as unknown as ListEventsArgs;
const events = await calendar.listEvents(
args.calendarId,
args.maxResults
);
return {
content: [
{
type: "text",
text: JSON.stringify(events, null, 2),
},
],
};
}
case "systemprompt_get_event": {
const calendar = new CalendarService();
const args = request.params.arguments as unknown as GetEventArgs;
const event = await calendar.getEvent(args.eventId, args.calendarId);
return {
content: [
{
type: "text",
text: JSON.stringify(event, null, 2),
},
],
};
}
case "systemprompt_search_events": {
const calendar = new CalendarService();
const args = request.params.arguments as unknown as SearchEventsArgs;
const events = await calendar.searchEvents(
args.query,
args.calendarId,
args.maxResults
);
return {
content: [
{
type: "text",
text: JSON.stringify(events, null, 2),
},
],
};
}
case "systemprompt_list_calendars": {
const calendar = new CalendarService();
const calendars = await calendar.listCalendars();
return {
content: [
{
type: "text",
text: JSON.stringify(calendars, null, 2),
},
],
};
}
case "systemprompt_send_email": {
const gmail = new GmailService();
const args = request.params.arguments as unknown as SendEmailOptions;
const messageId = await gmail.sendEmail({
to: args.to,
subject: args.subject,
body: args.body,
cc: args.cc,
bcc: args.bcc,
isHtml: args.isHtml,
});
return {
content: [
{
type: "text",
text: JSON.stringify({
messageId,
status: "Email sent successfully",
}),
},
],
};
}
case "systemprompt_create_draft": {
const gmail = new GmailService();
const args = request.params.arguments as unknown as DraftEmailOptions;
const draftId = await gmail.createDraft({
to: args.to,
subject: args.subject,
body: args.body,
cc: args.cc,
bcc: args.bcc,
isHtml: args.isHtml,
});
return {
content: [
{
type: "text",
text: JSON.stringify({
draftId,
status: "Draft created successfully",
}),
},
],
};
}
case "systemprompt_list_drafts": {
const gmail = new GmailService();
const args = request.params.arguments as unknown as {
maxResults?: number;
};
const drafts = await gmail.listDrafts(args.maxResults);
return {
content: [
{
type: "text",
text: JSON.stringify(drafts, null, 2),
},
],
};
}
case "systemprompt_delete_draft": {
const gmail = new GmailService();
const args = request.params.arguments as unknown as { draftId: string };
await gmail.deleteDraft(args.draftId);
return {
content: [
{
type: "text",
text: JSON.stringify({ status: "Draft deleted successfully" }),
},
],
};
}
default:
throw new Error(`Unknown tool: ${request.params.name}`);
}
} catch (error: any) {
console.error("Tool call failed:", error);
throw new Error(`Tool call failed: ${error.message || "Unknown error"}`);
}
}