Skip to main content
Glama
TRANZACT

Tempo Filler MCP Server

Official
by TRANZACT

post_worklog

Log work hours in JIRA Tempo by creating time entries with issue keys, dates, and descriptions for accurate time tracking.

Instructions

Create a new worklog entry. For better results, consider using get_schedule first to verify working days and expected hours.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
issueKeyYesJIRA issue key (e.g., PROJ-1234)
hoursYesHours worked (decimal)
startDateYesStart date in YYYY-MM-DD format
endDateNoEnd date in YYYY-MM-DD format (optional, defaults to startDate)
billableNoWhether the time is billable (default: true)
descriptionNoWork description (optional)

Implementation Reference

  • The postWorklog function implementing the core tool logic: parses input, creates Tempo worklog payload, calls API, handles response and errors with formatted markdown output.
    export async function postWorklog(
      tempoClient: TempoClient,
      input: PostWorklogInput
    ): Promise<CallToolResult> {
      try {
        const { 
          issueKey, 
          hours, 
          startDate, 
          endDate, 
          billable = true, 
          description 
        } = input;
    
        // Create the worklog payload using the Tempo client (automatically uses authenticated user)
        const payload = await tempoClient.createWorklogPayload({
          issueKey,
          hours,
          startDate,
          endDate,
          billable,
          description
        });
    
        // Create the worklog
        const worklogResponse = await tempoClient.createWorklog(payload);
    
        // Handle the response - API returns an array with a single worklog object
        const worklog = Array.isArray(worklogResponse) ? worklogResponse[0] : worklogResponse;
    
        // Format success response
        const actualEndDate = endDate || startDate;
        const billableHours = billable ? hours : 0;
        
        let displayText = `## Worklog Created Successfully\n\n`;
        displayText += `**Issue:** ${issueKey} - ${worklog.issue.summary}\n`;
        displayText += `**Hours:** ${hours}h`;
        if (billableHours !== hours) {
          displayText += ` (${billableHours}h billable)`;
        }
        displayText += `\n`;
        displayText += `**Date:** ${startDate}`;
        if (actualEndDate !== startDate) {
          displayText += ` to ${actualEndDate}`;
        }
        displayText += `\n`;
        
        if (description) {
          displayText += `**Description:** ${description}\n`;
        }
        
        displayText += `**Worklog ID:** ${worklog.tempoWorklogId || worklog.id}\n`;
        displayText += `**Time Spent:** ${worklog.timeSpent}\n`;
        
        // Add some helpful information
        displayText += `\n### Details\n`;
        displayText += `- Created at: ${new Date().toISOString()}\n`;
        displayText += `- Total seconds: ${worklog.timeSpentSeconds}\n`;
        displayText += `- Billable seconds: ${worklog.billableSeconds}\n`;
        
        return {
          content: [
            {
              type: "text",
              text: displayText
            }
          ],
          isError: false
        };
    
      } catch (error) {
        let errorMessage = error instanceof Error ? error.message : String(error);
        
        // Provide more helpful error messages for common issues
        if (errorMessage.includes('not found')) {
          errorMessage += `\n\nTip: Make sure the issue key '${input.issueKey}' exists and you have access to it.`;
        } else if (errorMessage.includes('Authentication failed')) {
          errorMessage += `\n\nTip: Check your Personal Access Token (PAT) in the TEMPO_PAT environment variable.`;
        } else if (errorMessage.includes('Access forbidden')) {
          errorMessage += `\n\nTip: Make sure you have permission to log time to this issue and that Tempo is properly configured.`;
        }
        
        return {
          content: [
            {
              type: "text",
              text: `## Error Creating Worklog\n\n**Issue:** ${input.issueKey}\n**Hours:** ${input.hours}\n**Date:** ${input.startDate}\n\n**Error:** ${errorMessage}`
            }
          ],
          isError: true
        };
      }
    }
  • Zod schema defining input validation for post_worklog tool parameters.
    export const PostWorklogInputSchema = z.object({
      issueKey: z.string().min(1, "Issue key is required"),
      hours: z.number().min(0.1, "Hours must be at least 0.1").max(24, "Hours cannot exceed 24"),
      startDate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "Start date must be in YYYY-MM-DD format"),
      endDate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "End date must be in YYYY-MM-DD format").optional(),
      billable: z.boolean().optional(),
      description: z.string().optional(),
    });
  • src/index.ts:226-229 (registration)
    MCP server registration: handles execution of post_worklog tool by parsing input schema and calling the handler function.
    case TOOL_NAMES.POST_WORKLOG: {
      const input = PostWorklogInputSchema.parse(args);
      return await postWorklog(tempoClient, input);
    }
  • src/index.ts:97-133 (registration)
    MCP server registration: declares post_worklog tool metadata including name, description, and input schema for ListTools requests.
      name: TOOL_NAMES.POST_WORKLOG,
      description: "Create a new worklog entry. For better results, consider using get_schedule first to verify working days and expected hours.",
      inputSchema: {
        type: "object",
        properties: {
          issueKey: {
            type: "string",
            description: "JIRA issue key (e.g., PROJ-1234)",
          },
          hours: {
            type: "number",
            minimum: 0.1,
            maximum: 24,
            description: "Hours worked (decimal)",
          },
          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 (optional, defaults to startDate)",
          },
          billable: {
            type: "boolean",
            description: "Whether the time is billable (default: true)",
          },
          description: {
            type: "string",
            description: "Work description (optional)",
          },
        },
        required: ["issueKey", "hours", "startDate"],
      },
    },
  • Tool name constant used for registration and identification.
    POST_WORKLOG: "post_worklog",

Tool Definition Quality

Score is being calculated. Check back soon.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/TRANZACT/tempo-filler-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server