@clicktime/mcp-server
Version:
ClickTime MCP Tech Demo for AI agents to interact with ClickTime API
388 lines (387 loc) • 13.8 kB
JavaScript
// src/tools.ts
import { createExpenseTools } from './expense/expense-tools.js';
import { createSubmissionTools } from './submission/submission-tools.js';
export function createTimeEntryTools(client) {
return [
{
name: 'add_time_entry',
description: 'Add a time entry for a specific project/task',
inputSchema: {
type: 'object',
properties: {
date: {
type: 'string',
pattern: '^\\d{4}-\\d{2}-\\d{2}$',
description: 'Date in YYYY-MM-DD format',
},
hours: {
type: 'number',
minimum: 0,
maximum: 24,
description: 'Hours worked (0-24)',
},
jobId: {
type: 'string',
description: 'Job/Project ID',
},
taskId: {
type: 'string',
description: 'Task ID',
},
comment: {
type: 'string',
description: 'Optional work description',
},
},
required: ['date', 'hours', 'jobId', 'taskId'],
},
},
{
name: 'get_recent_time_entries',
description: 'Get recent time entries, optionally filtered by date range',
inputSchema: {
type: 'object',
properties: {
startDate: {
type: 'string',
pattern: '^\\d{4}-\\d{2}-\\d{2}$',
description: 'Start date in YYYY-MM-DD format',
},
endDate: {
type: 'string',
pattern: '^\\d{4}-\\d{2}-\\d{2}$',
description: 'End date in YYYY-MM-DD format',
},
limit: {
type: 'number',
minimum: 1,
maximum: 500,
default: 50,
description: 'Maximum number of entries to return',
},
},
},
},
{
name: 'update_time_entry',
description: 'Update an existing time entry',
inputSchema: {
type: 'object',
properties: {
entryId: {
type: 'string',
description: 'Time entry ID to update',
},
date: {
type: 'string',
pattern: '^\\d{4}-\\d{2}-\\d{2}$',
description: 'Date in YYYY-MM-DD format',
},
hours: {
type: 'number',
minimum: 0,
maximum: 24,
description: 'Hours worked',
},
jobId: {
type: 'string',
description: 'Job/Project ID',
},
taskId: {
type: 'string',
description: 'Task ID',
},
comment: {
type: 'string',
description: 'Work description',
},
},
required: ['entryId'],
},
},
{
name: 'delete_time_entry',
description: 'Delete a time entry permanently',
inputSchema: {
type: 'object',
properties: {
entryId: {
type: 'string',
description: 'Time entry ID to delete',
},
},
required: ['entryId'],
},
},
];
}
export function createProjectTools(client) {
return [
{
name: 'list_my_projects',
description: 'List all projects (jobs) available for time entry',
inputSchema: {
type: 'object',
properties: {
activeOnly: {
type: 'boolean',
default: true,
description: 'Only show active projects',
},
},
},
},
{
name: 'get_project_details',
description: 'Get detailed information about a specific project',
inputSchema: {
type: 'object',
properties: {
jobId: {
type: 'string',
description: 'Project/Job ID',
},
},
required: ['jobId'],
},
},
{
name: 'list_my_tasks',
description: 'List all tasks available for time entry',
inputSchema: {
type: 'object',
properties: {
activeOnly: {
type: 'boolean',
default: true,
description: 'Only show active tasks',
},
},
},
},
{
name: 'get_task_details',
description: 'Get detailed information about a specific task',
inputSchema: {
type: 'object',
properties: {
taskId: {
type: 'string',
description: 'Task ID',
},
},
required: ['taskId'],
},
},
];
}
export function createTimeOffTools(client) {
return [
{
name: 'create_time_off_request',
description: 'Create a time off request for specified dates. Automatically routes to approval or non-approval endpoint based on time off type.',
inputSchema: {
type: 'object',
properties: {
startDate: {
type: 'string',
pattern: '^\\d{4}-\\d{2}-\\d{2}$',
description: 'Start date of time off (YYYY-MM-DD)',
},
endDate: {
type: 'string',
pattern: '^\\d{4}-\\d{2}-\\d{2}$',
description: 'End date of time off (YYYY-MM-DD)',
},
timeOffTypeId: {
type: 'string',
description: 'Type of time off (vacation, sick, etc.)',
},
notes: {
type: 'string',
description: 'Optional notes for the request',
},
hoursPerDay: {
type: 'number',
description: 'Hours per day for non-approval time off (default: 8)',
minimum: 0,
maximum: 24,
},
dcaaExplanation: {
type: 'string',
description: 'DCAA explanation (only for DCAA companies, past time entries)',
maxLength: 2000,
},
},
required: ['startDate', 'endDate', 'timeOffTypeId'],
},
},
{
name: 'remove_time_off',
description: "Remove any time off (RECOMMENDED): Automatically determines whether to delete an entry or cancel a request based on the ID",
inputSchema: {
type: 'object',
properties: {
id: {
type: 'string',
description: 'ID of the time off entry or request to remove',
},
comment: {
type: 'string',
description: 'Optional comment (used if cancelling a request)',
maxLength: 2000,
},
dcaaExplanation: {
type: 'string',
description: 'Optional DCAA explanation (used if deleting an entry)',
},
},
required: ['id'],
},
},
{
name: 'get_time_off',
description: "Get user's time off entries",
inputSchema: {
type: 'object',
properties: {
ids: {
type: 'array',
items: { type: 'string' },
description: 'Filter by specific time off entry IDs',
},
timeOffTypeIds: {
type: 'array',
items: { type: 'string' },
description: 'Filter by time off type IDs',
},
fromDate: {
type: 'string',
pattern: '^\\d{4}-\\d{2}-\\d{2}$',
description: 'Filter from this date (inclusive)',
},
toDate: {
type: 'string',
pattern: '^\\d{4}-\\d{2}-\\d{2}$',
description: 'Filter to this date (inclusive)',
},
dates: {
type: 'array',
items: {
type: 'string',
pattern: '^\\d{4}-\\d{2}-\\d{2}$'
},
description: 'Filter by specific dates',
},
limit: {
type: 'integer',
description: 'Maximum number of entries to return',
},
offset: {
type: 'integer',
description: 'Number of entries to skip for pagination',
},
},
},
},
{
name: 'get_time_off_requests',
description: "Get user's time off requests",
inputSchema: {
type: 'object',
properties: {
startDate: {
type: 'string',
pattern: '^\\d{4}-\\d{2}-\\d{2}$',
description: 'Filter from this start date',
},
endDate: {
type: 'string',
pattern: '^\\d{4}-\\d{2}-\\d{2}$',
description: 'Filter to this end date',
},
},
},
},
{
name: 'get_time_off_request_details',
description: "Get detailed information about a specific time off request",
inputSchema: {
type: 'object',
properties: {
requestId: {
type: 'string',
description: 'ID of the time off request to retrieve',
},
},
required: ['requestId'],
},
},
{
name: 'get_time_off_request_actions',
description: "Get available actions for a time off request (e.g., Cancel)",
inputSchema: {
type: 'object',
properties: {
requestId: {
type: 'string',
description: 'ID of the time off request',
},
},
required: ['requestId'],
},
},
{
name: 'get_time_off_balance',
description: 'Get current time off balance by type',
inputSchema: {
type: 'object',
properties: {
timeOffTypeId: {
type: 'string',
description: 'Time off type ID to check balance for',
},
},
required: ['timeOffTypeId'],
},
},
{
name: 'list_time_off_types',
description: 'List all available time off types',
inputSchema: {
type: 'object',
properties: {},
},
},
];
}
export function createUserTools(client) {
return [
{
name: 'get_my_profile',
description: 'Get current user profile information',
inputSchema: {
type: 'object',
properties: {},
},
},
{
name: 'get_version',
description: 'Get the current version of the ClickTime MCP Server',
inputSchema: {
type: 'object',
properties: {},
},
},
];
}
export function getAllTools(client) {
return [
...createTimeEntryTools(client),
...createProjectTools(client),
...createTimeOffTools(client),
...createExpenseTools(client),
...createSubmissionTools(client),
...createUserTools(client),
];
}