@meetbot/mcp
Version:
Model Context Protocol (MCP) server for Meet.bot booking page API
282 lines • 11.7 kB
JavaScript
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
import { MeetbotClient } from './meetbot-client.js';
/**
* MCP Server for Meet.bot Booking Page API
*/
export class MeetbotMCPServer {
server;
client = null;
constructor() {
this.server = new Server({
name: 'meetbot-mcp',
version: '1.0.0',
});
this.setupToolHandlers();
}
setupToolHandlers() {
// List available tools
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: 'configure_meetbot',
description: 'Configure the Meet.bot API client with authentication',
inputSchema: {
type: 'object',
properties: {
authToken: {
type: 'string',
description: 'Bearer token for authentication (optional)',
},
},
required: [],
},
},
{
name: 'get_scheduling_pages',
description: 'Get all scheduling pages for the authenticated user',
inputSchema: {
type: 'object',
properties: {},
},
},
{
name: 'get_page_info',
description: 'Get information about a specific scheduling page',
inputSchema: {
type: 'object',
properties: {
page: {
type: 'string',
description: 'The URL of the scheduling page',
},
},
required: ['page'],
},
},
{
name: 'get_available_slots',
description: 'Get available booking slots for a scheduling page',
inputSchema: {
type: 'object',
properties: {
page: {
type: 'string',
description: 'The URL of the scheduling page',
},
count: {
type: 'number',
description: 'Maximum number of slots to return',
},
start: {
type: 'string',
description: 'Start date in YYYY-MM-DD format',
},
end: {
type: 'string',
description: 'End date in YYYY-MM-DD format',
},
timezone: {
type: 'string',
description: 'Timezone in IANA format (e.g., America/New_York)',
},
booking_link: {
type: 'boolean',
description: 'Include shareable booking links',
},
},
required: ['page'],
},
},
{
name: 'book_meeting',
description: 'Book a new meeting slot',
inputSchema: {
type: 'object',
properties: {
page: {
type: 'string',
description: 'The URL of the scheduling page',
},
guest_email: {
type: 'string',
description: 'Email address of the guest',
},
guest_name: {
type: 'string',
description: 'Name of the guest',
},
notes: {
type: 'string',
description: 'Additional notes for the meeting',
},
start: {
type: 'string',
description: 'Start time in ISO 8601 format',
},
},
required: ['page', 'guest_email', 'guest_name', 'start'],
},
},
{
name: 'health_check',
description: 'Check if the Meet.bot API client is properly configured and can connect',
inputSchema: {
type: 'object',
properties: {},
},
},
],
};
});
// Handle tool calls
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
try {
switch (name) {
case 'configure_meetbot':
return await this.handleConfigureMeetbot(args);
case 'get_scheduling_pages':
return await this.handleGetSchedulingPages(args);
case 'get_page_info':
return await this.handleGetPageInfo(args);
case 'get_available_slots':
return await this.handleGetAvailableSlots(args);
case 'book_meeting':
return await this.handleBookMeeting(args);
case 'health_check':
return await this.handleHealthCheck(args);
default:
throw new Error(`Unknown tool: ${name}`);
}
}
catch (error) {
return {
content: [
{
type: 'text',
text: `Error: ${error instanceof Error ? error.message : String(error)}`,
},
],
isError: true,
};
}
});
}
async handleConfigureMeetbot(args) {
if (!this.client) {
this.client = new MeetbotClient(args);
return {
content: [
{
type: 'text',
text: 'Meet.bot API client configured successfully.',
},
],
};
}
else {
// Reconfigure existing client
this.client = new MeetbotClient(args);
return {
content: [
{
type: 'text',
text: 'Meet.bot API client reconfigured successfully.',
},
],
};
}
}
async handleGetSchedulingPages(_args) {
if (!this.client) {
throw new Error('Meet.bot client not configured. Please run configure_meetbot first.');
}
const pages = await this.client.getPages();
return {
content: [
{
type: 'text',
text: `Found ${pages.pages.length} scheduling pages for ${pages.email}:\n\n${pages.pages
.map((page) => `• ${page.title} (${page.duration} min) - ${page.url}`)
.join('\n')}`,
},
],
};
}
async handleGetPageInfo(args) {
if (!this.client) {
throw new Error('Meet.bot client not configured. Please run configure_meetbot first.');
}
const pageInfo = await this.client.getPageInfo(args);
return {
content: [
{
type: 'text',
text: `Page Information:\n\nTitle: ${pageInfo.title}\nDuration: ${pageInfo.duration} minutes\nOwner: ${pageInfo.owner_name}\nMax days ahead: ${pageInfo.max_days_into_the_future}\nURL: ${pageInfo.url}`,
},
],
};
}
async handleGetAvailableSlots(args) {
if (!this.client) {
throw new Error('Meet.bot client not configured. Please run configure_meetbot first.');
}
const slots = await this.client.getSlots(args);
return {
content: [
{
type: 'text',
text: `Found ${slots.count} available slots (${slots.duration} min each):\n\n${slots.slots
.map((slot) => {
const date = new Date(slot.start).toLocaleString();
const urlInfo = slot.url ? `\n Booking link: ${slot.url}` : '';
return `• ${date}${urlInfo}`;
})
.join('\n\n')}`,
},
],
};
}
async handleBookMeeting(args) {
if (!this.client) {
throw new Error('Meet.bot client not configured. Please run configure_meetbot first.');
}
const booking = await this.client.bookSlot(args);
return {
content: [
{
type: 'text',
text: `Meeting booked successfully!\n\nGuest: ${booking.guest_name} (${booking.guest_email})\nStart: ${new Date(booking.start).toLocaleString()}\nCalendar ID: ${booking.ical_uid}\nPage: ${booking.page}`,
},
],
};
}
async handleHealthCheck(_args) {
if (!this.client) {
throw new Error('Meet.bot client not configured. Please run configure_meetbot first.');
}
const isHealthy = await this.client.healthCheck();
return {
content: [
{
type: 'text',
text: isHealthy
? '✅ Meet.bot API client is healthy and can connect to the API.'
: '❌ Meet.bot API client cannot connect to the API. Please check your configuration.',
},
],
};
}
/**
* Start the MCP server
*/
async run() {
const transport = new StdioServerTransport();
await this.server.connect(transport);
console.error('Meet.bot MCP server started');
}
}
//# sourceMappingURL=mcp-server.js.map