// MCP Server configuration and tool registration
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import {
CallToolRequestSchema,
ListToolsRequestSchema,
} from '@modelcontextprotocol/sdk/types.js';
import type { OAuth2Client } from 'google-auth-library';
import { DriveService, DocsService, SheetsService, SlidesService, CalendarService, GmailService, MeetService, TasksService, ContactsService } from './services/index.js';
import { fileTools, createFileHandlers } from './tools/files.js';
import { folderTools, createFolderHandlers } from './tools/folders.js';
import { docsTools, createDocsHandlers } from './tools/docs.js';
import { sheetsTools, createSheetsHandlers } from './tools/sheets.js';
import { slidesTools, createSlidesHandlers } from './tools/slides.js';
import { accountTools, createAccountHandlers } from './tools/account.js';
import { binaryTools, createBinaryHandlers } from './tools/binary.js';
import { calendarTools, createCalendarHandlers } from './tools/calendar.js';
import { gmailTools, createGmailHandlers } from './tools/gmail.js';
import { meetTools, createMeetHandlers } from './tools/meet.js';
import { tasksTools, createTasksHandlers } from './tools/tasks.js';
import { contactsTools, createContactsHandlers } from './tools/contacts.js';
import { permissionsTools, createPermissionsHandlers } from './tools/permissions.js';
import { formatError } from './utils/errors.js';
import { isEnabled } from './config/services.js';
const SERVER_NAME = 'google-workspace-mcp';
const SERVER_VERSION = '0.3.0';
export function createServer(authClient: OAuth2Client): Server {
const server = new Server(
{ name: SERVER_NAME, version: SERVER_VERSION },
{ capabilities: { tools: {} } }
);
// Initialize services
const driveService = new DriveService(authClient);
const docsService = new DocsService(authClient, driveService);
const sheetsService = new SheetsService(authClient, driveService);
const slidesService = new SlidesService(authClient);
// Create handlers for always-enabled services
const fileHandlers = createFileHandlers(driveService);
const folderHandlers = createFolderHandlers(driveService);
const docsHandlers = createDocsHandlers(docsService);
const sheetsHandlers = createSheetsHandlers(sheetsService);
const slidesHandlers = createSlidesHandlers(slidesService);
const accountHandlers = createAccountHandlers(driveService);
const binaryHandlers = createBinaryHandlers(driveService);
const permissionsHandlers = createPermissionsHandlers(driveService);
// Combine base handlers
const handlers: Record<string, (args: unknown) => Promise<unknown>> = {
...fileHandlers as Record<string, (args: unknown) => Promise<unknown>>,
...folderHandlers as Record<string, (args: unknown) => Promise<unknown>>,
...docsHandlers as Record<string, (args: unknown) => Promise<unknown>>,
...sheetsHandlers as Record<string, (args: unknown) => Promise<unknown>>,
...slidesHandlers as Record<string, (args: unknown) => Promise<unknown>>,
...accountHandlers as Record<string, (args: unknown) => Promise<unknown>>,
...binaryHandlers as Record<string, (args: unknown) => Promise<unknown>>,
...permissionsHandlers as Record<string, (args: unknown) => Promise<unknown>>,
};
// Base tools (always available)
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let allTools: any[] = [...fileTools, ...folderTools, ...docsTools, ...sheetsTools, ...slidesTools, ...accountTools, ...binaryTools, ...permissionsTools];
// Conditionally add Calendar service and tools
if (isEnabled('calendar')) {
const calendarService = new CalendarService(authClient);
const calendarHandlers = createCalendarHandlers(calendarService);
Object.assign(handlers, calendarHandlers as Record<string, (args: unknown) => Promise<unknown>>);
allTools = [...allTools, ...calendarTools];
}
// Conditionally add Gmail service and tools
if (isEnabled('gmail')) {
const gmailService = new GmailService(authClient);
const gmailHandlers = createGmailHandlers(gmailService);
Object.assign(handlers, gmailHandlers as Record<string, (args: unknown) => Promise<unknown>>);
allTools = [...allTools, ...gmailTools];
}
// Conditionally add Meet service and tools
if (isEnabled('meet')) {
const meetService = new MeetService(authClient);
const meetHandlers = createMeetHandlers(meetService);
Object.assign(handlers, meetHandlers as Record<string, (args: unknown) => Promise<unknown>>);
allTools = [...allTools, ...meetTools];
}
// Conditionally add Tasks service and tools
if (isEnabled('tasks')) {
const tasksService = new TasksService(authClient);
const tasksHandlers = createTasksHandlers(tasksService);
Object.assign(handlers, tasksHandlers as Record<string, (args: unknown) => Promise<unknown>>);
allTools = [...allTools, ...tasksTools];
}
// Conditionally add Contacts service and tools
if (isEnabled('contacts')) {
const contactsService = new ContactsService(authClient);
const contactsHandlers = createContactsHandlers(contactsService);
Object.assign(handlers, contactsHandlers as Record<string, (args: unknown) => Promise<unknown>>);
allTools = [...allTools, ...contactsTools];
}
// Register tool list handler
server.setRequestHandler(ListToolsRequestSchema, async () => {
return { tools: allTools };
});
// Register tool call handler
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
const handler = handlers[name];
if (!handler) {
return {
content: [{ type: 'text', text: JSON.stringify({ error: `Unknown tool: ${name}` }) }],
isError: true,
};
}
try {
const result = await handler(args);
return {
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
};
} catch (error) {
return {
content: [{ type: 'text', text: JSON.stringify(formatError(error)) }],
isError: true,
};
}
});
return server;
}