@brandcast_app/zoomshift-mcp-server
Version:
Model Context Protocol server for ZoomShift employee scheduling. Use ZoomShift with Claude Desktop.
252 lines • 9.06 kB
JavaScript
/**
* MCP Tool definitions and handlers for ZoomShift
*/
export const ZOOMSHIFT_TOOLS = [
{
name: 'zoomshift_get_shifts',
description: 'Get employee shifts for a date range',
inputSchema: {
type: 'object',
properties: {
start_date: {
type: 'string',
description: 'Start date in YYYY-MM-DD format',
},
end_date: {
type: 'string',
description: 'End date in YYYY-MM-DD format',
},
},
required: ['start_date', 'end_date'],
},
},
{
name: 'zoomshift_get_employee_shifts',
description: 'Get shifts for a specific employee',
inputSchema: {
type: 'object',
properties: {
employee_id: {
type: 'string',
description: 'The ID of the employee',
},
start_date: {
type: 'string',
description: 'Start date in YYYY-MM-DD format',
},
end_date: {
type: 'string',
description: 'End date in YYYY-MM-DD format',
},
},
required: ['employee_id', 'start_date', 'end_date'],
},
},
{
name: 'zoomshift_get_locations',
description: 'Get all locations in the schedule',
inputSchema: {
type: 'object',
properties: {},
},
},
{
name: 'zoomshift_get_employees',
description: 'Get all employees in the schedule',
inputSchema: {
type: 'object',
properties: {},
},
},
{
name: 'zoomshift_get_positions',
description: 'Get all job positions/roles in the schedule',
inputSchema: {
type: 'object',
properties: {},
},
},
{
name: 'zoomshift_search_shifts',
description: 'Search for shifts by employee name, role, or location',
inputSchema: {
type: 'object',
properties: {
query: {
type: 'string',
description: 'Search query (employee name, role, or location)',
},
start_date: {
type: 'string',
description: 'Start date in YYYY-MM-DD format',
},
end_date: {
type: 'string',
description: 'End date in YYYY-MM-DD format',
},
},
required: ['query', 'start_date', 'end_date'],
},
},
];
/**
* Execute a ZoomShift tool
*/
export async function executeTool(toolName, args, client) {
switch (toolName) {
case 'zoomshift_get_shifts': {
const shifts = await client.getShifts({
startDate: args.start_date,
endDate: args.end_date,
});
return {
shifts: shifts.map(shift => ({
id: shift.id,
employee_name: shift.employeeName,
employee_id: shift.employeeId,
role: shift.role,
start_time: shift.startTime,
end_time: shift.endTime,
duration_hours: shift.duration,
break_hours: shift.breakDuration,
location: shift.location,
notes: shift.notes,
status: shift.status,
})),
count: shifts.length,
};
}
case 'zoomshift_get_employee_shifts': {
const shifts = await client.getShifts({
startDate: args.start_date,
endDate: args.end_date,
employeeId: args.employee_id,
});
return {
employee_id: args.employee_id,
shifts: shifts.map(shift => ({
id: shift.id,
role: shift.role,
start_time: shift.startTime,
end_time: shift.endTime,
duration_hours: shift.duration,
break_hours: shift.breakDuration,
location: shift.location,
notes: shift.notes,
status: shift.status,
})),
count: shifts.length,
};
}
case 'zoomshift_get_locations': {
// Get recent shifts to extract location list
const endDate = new Date();
const startDate = new Date();
startDate.setDate(startDate.getDate() - 30); // Last 30 days
const shifts = await client.getShifts({
startDate: startDate.toISOString().split('T')[0],
endDate: endDate.toISOString().split('T')[0],
});
// Extract unique locations
const locationSet = new Set();
shifts.forEach(shift => {
if (shift.location) {
locationSet.add(shift.location);
}
});
const locations = Array.from(locationSet).map((name, index) => ({
id: `loc_${index}`,
name,
}));
return {
locations,
count: locations.length,
};
}
case 'zoomshift_get_employees': {
// Get recent shifts to extract employee list
const endDate = new Date();
const startDate = new Date();
startDate.setDate(startDate.getDate() - 30); // Last 30 days
const shifts = await client.getShifts({
startDate: startDate.toISOString().split('T')[0],
endDate: endDate.toISOString().split('T')[0],
});
// Extract unique employees
const employeeMap = new Map();
shifts.forEach(shift => {
if (!employeeMap.has(shift.employeeId)) {
employeeMap.set(shift.employeeId, {
id: shift.employeeId,
full_name: shift.employeeName,
positions: new Set(),
});
}
employeeMap.get(shift.employeeId).positions.add(shift.role);
});
const employees = Array.from(employeeMap.values()).map(emp => ({
id: emp.id,
full_name: emp.full_name,
positions: Array.from(emp.positions),
}));
return {
employees,
count: employees.length,
};
}
case 'zoomshift_get_positions': {
// Get recent shifts to extract position list
const endDate = new Date();
const startDate = new Date();
startDate.setDate(startDate.getDate() - 30); // Last 30 days
const shifts = await client.getShifts({
startDate: startDate.toISOString().split('T')[0],
endDate: endDate.toISOString().split('T')[0],
});
// Extract unique positions
const positionSet = new Set();
shifts.forEach(shift => {
if (shift.role) {
positionSet.add(shift.role);
}
});
const positions = Array.from(positionSet).map((name, index) => ({
id: `pos_${index}`,
name,
}));
return {
positions,
count: positions.length,
};
}
case 'zoomshift_search_shifts': {
const shifts = await client.getShifts({
startDate: args.start_date,
endDate: args.end_date,
});
const query = args.query.toLowerCase();
const matchingShifts = shifts.filter(shift => shift.employeeName.toLowerCase().includes(query) ||
shift.role.toLowerCase().includes(query) ||
shift.location?.toLowerCase().includes(query));
return {
query: args.query,
shifts: matchingShifts.map(shift => ({
id: shift.id,
employee_name: shift.employeeName,
employee_id: shift.employeeId,
role: shift.role,
start_time: shift.startTime,
end_time: shift.endTime,
duration_hours: shift.duration,
location: shift.location,
notes: shift.notes,
status: shift.status,
})),
count: matchingShifts.length,
};
}
default:
throw new Error(`Unknown tool: ${toolName}`);
}
}
//# sourceMappingURL=tools.js.map