Skip to content

feat: add worklog analytics tools and harden auth/error handling#25

Merged
ivelin-web merged 1 commit into
mainfrom
feat/worklog-insights
Apr 29, 2026
Merged

feat: add worklog analytics tools and harden auth/error handling#25
ivelin-web merged 1 commit into
mainfrom
feat/worklog-insights

Conversation

@ivelin-web

Copy link
Copy Markdown
Owner

Summary

Adds two new MCP tools for worklog insights, plus several bug fixes that surfaced while wiring them up.

New tools

  • getMissingWorklogDays — finds working days where logged time is below the user's expected schedule. Uses Tempo's user-schedule API so holidays, non-working days, and part-time schedules are honoured automatically. Per-issue breakdown for partially-logged days.
  • getWorklogAnalytics — aggregates worklogs by issue / account / day / week (ISO 8601) / month. Returns hours, percentage, worklog count per group sorted by hours desc.

Bug fixes (surfaced during integration)

  • getCurrentUserAccountId now prefers /rest/api/3/myself for all auth types, with the email-search retained as a basic-auth fallback. Avoids empty results when Atlassian privacy or scoped-token restrictions hide email visibility.
  • All 7 tool wrappers now propagate isError correctly. bulkCreateWorklogs was especially affected — full-batch failures were silently reported as successes because the wrapper was dropping its explicit isError flag.
  • Pagination MAX_PAGES limit now throws instead of silent truncation. Returning incomplete data was worse than failing loudly.
  • 403 from /user-schedule surfaces a clear scope-guidance message instead of an opaque axios error.

Polish & optimisation

  • limit=1000 on Tempo paginated requests — typical month-long queries now fit in a single round trip.
  • formatHours / formatPercent helpers drop trailing zeros (7.5h, 50%).
  • validateDateRange rejects startDate > endDate with a clear MCP error.
  • Cleaner output: single text block per response, no leading dashes (which clashed visually with em-dashes in issue titles), two-line layout for issue grouping.
  • Consolidated getIssueInfoMap helper (resolves key + summary in one pass); removed dead getIssueKeysMap / getIssueKeyById.

Docs

  • README clarifies classic vs scoped Jira API tokens and the OAuth fallback for orgs that disable classic tokens.
  • .env.example notes the Schemes scope requirement for Tempo.
  • Tool descriptions added in index.ts including the account groupBy caveat.

Bumps to 1.6.0.

Test plan

  • npm run build clean
  • npm run lint — 0 errors
  • npm run format:check clean
  • getMissingWorklogDays tested against live Tempo: zero-logged days, partially-logged days with breakdown, full week with no missing
  • getWorklogAnalytics tested with groupBy: issue (returns key + Jira summary, percentages sum to 100%)
  • 403 scope error verified — gives clear guidance message
  • Empty schedule case — returns informative message, not error
  • OAuth and bearer auth paths not tested in this PR (changed via /myself preference; existing logic preserved)
  • Inverted date range (startDate > endDate) verified to short-circuit with the new guard
  • bulkCreateWorklogs full-batch failure — verify isError now reaches the MCP client (existing behaviour was silently success)

Notes for reviewers

  • The "Create API token with scopes" Atlassian flow does not work with this server's basic auth path (scoped tokens require the api.atlassian.com/ex/jira/{cloudId} gateway). README now calls this out and points to OAuth as the workaround. A follow-up PR could add native scoped-token support via a JIRA_CLOUD_ID env var.
  • The account groupBy in getWorklogAnalytics only makes sense if your team uses Tempo accounts (_Account_ work attribute on worklogs). Documented in the tool description.

New tools:
- getMissingWorklogDays — find working days where logged time is below
  the user's expected schedule. Uses Tempo's user-schedule API so
  holidays, non-working days, and part-time schedules are honoured
  automatically. Per-issue breakdown for partially-logged days.
- getWorklogAnalytics — aggregate worklogs by issue, account, day,
  week (ISO 8601), or month. Returns hours, percentage, worklog count
  per group sorted by hours descending.

Bug fixes (surfaced while wiring up the new tools):
- getCurrentUserAccountId now prefers /rest/api/3/myself for all auth
  types, with email-search as basic-auth fallback. Avoids empty results
  when Atlassian privacy or scoped-token limits hide email visibility.
- All 7 tool wrappers now propagate isError correctly.
  bulkCreateWorklogs was especially affected — full-batch failures were
  silently reported as successes because the wrapper dropped its
  explicit isError flag.
- Pagination MAX_PAGES now throws instead of silent truncation.
  Returning incomplete data was worse than failing loudly.
- 403 from /user-schedule surfaces a clear scope-guidance message
  instead of an opaque axios error.

Polish & optimisation:
- limit=1000 on Tempo paginated requests — typical month-long queries
  now fit in a single round trip.
- formatHours/formatPercent helpers drop trailing zeros (7.5h, 50%).
- validateDateRange rejects startDate > endDate with a clear message.
- Cleaner output: single text block per response, no leading dashes
  (which clashed with em-dashes in issue titles), two-line layout for
  issue grouping in analytics (key+title above, stats indented below).
- Consolidated getIssueInfoMap helper resolves key + summary in one
  pass; removed dead getIssueKeysMap / getIssueKeyById.

Docs:
- README clarifies classic vs scoped Jira API tokens and the OAuth
  fallback for orgs that disable classic tokens.
- .env.example notes the Schemes scope requirement for Tempo.
- Tool descriptions added in index.ts including the account groupBy
  caveat.

Bumps to 1.6.0.
@ivelin-web ivelin-web merged commit e50a23a into main Apr 29, 2026
1 check passed
@ivelin-web ivelin-web deleted the feat/worklog-insights branch April 29, 2026 10:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant