MCP server for Tempo — natural-language time-tracking and resource planning via the Tempo API.
Add to .mcp.json in your project or ~/.claude/mcp.json:
json
{
"mcpServers": {
"tempo": {
"command": "npx",
"args": ["-y", "tempo-api-mcp"],
"env": {
"TEMPO_API_TOKEN": "your-api-token-here"
}
}
}
}
bash
git clone https://github.com/chrischall/tempo-api-mcp
cd tempo-api-mcp
npm install && npm run build
Then add to .mcp.json:
json
{
"mcpServers": {
"tempo": {
"command": "node",
"args": ["/path/to/tempo-api-mcp/dist/index.js"],
"env": {
"TEMPO_API_TOKEN": "your-api-token-here"
}
}
}
}
Or use a .env file in the project directory with TEMPO_API_TOKEN=<value>.
Bearer token auth — attached to every request as Authorization: Bearer <token>.
ToolDescriptiontempo_get_worklogs(..., view?)List worklogs with optional filters (project, issue, date range)tempo_get_worklog(id, view?)Get a single worklog by idtempo_create_worklog(authorAccountId, issueId, startDate, timeSpentSeconds, ...)Log time against a Jira issuetempo_update_worklog(id, timeSpentSeconds?, description?, attributes?, ...)Update an existing worklog — pass only what changes; omitted fields keep their current valuestempo_delete_worklog(id)Delete a worklogtempo_search_worklogs(authorIds?, issueIds?, projectIds?, from?, to?, ..., view?)Advanced search via POSTtempo_get_worklogs_by_user(accountId, from?, to?, updatedFrom?, view?)All worklogs for a usertempo_get_worklogs_by_project(projectId, from?, to?, updatedFrom?, view?)All worklogs for a Jira projecttempo_get_worklogs_by_issue(issueId, from?, to?, updatedFrom?, view?)All worklogs for a Jira issuetempo_get_worklogs_by_team(teamId, from?, to?, updatedFrom?, view?)All worklogs for a Tempo teamtempo_get_worklogs_by_account(accountKey, from?, to?, updatedFrom?, view?)All worklogs for a Tempo account
ToolDescriptiontempo_get_plans(from, to, ..., view?)List plans for a date rangetempo_get_plan(id, view?)Get a single plan by idtempo_create_plan(assigneeId, assigneeType, planItemId, planItemType, startDate, endDate, ...)Create a resource allocation plantempo_update_plan(id, ...)Update an existing plan — omitted fields keep their current valuestempo_delete_plan(id)Delete a plan
ToolDescriptiontempo_get_teams(..., view?)List teams with optional filterstempo_get_team(id, view?)Get a single team by idtempo_create_team(name, ...)Create a new teamtempo_update_team(id, name?, ...)Update a team — omitted fields keep their current valuestempo_delete_team(id)Delete a teamtempo_get_team_memberships(teamId, view?)All memberships for one teamtempo_search_team_memberships(teamIds?, accountIds?, roleIds?, view?)Membership search across teams via POST
ToolDescriptiontempo_get_accounts(view?)List all accounts (OPEN and CLOSED)tempo_get_account(id, view?)Get a single account by numeric idtempo_search_accounts(ids?, keys?, statuses?, global?, view?)Search accounts; also resolves a key to an idtempo_create_account(key, name, leadAccountId, status?, ...)Create a new account (status defaults to OPEN)tempo_update_account(key, name?, ...)Update an account — omitted fields keep their current valuestempo_delete_account(key)Delete an accounttempo_get_account_categories(id?, view?)List account categories (not paginated)
ToolDescriptiontempo_get_projects(view?)List Tempo Financial Manager projectstempo_get_project(id, view?)Get a project by idtempo_get_timesheet_approval_status(accountId, from, to?, view?)Get timesheet approval status for a usertempo_get_timesheet_approvals_waiting(view?)List timesheets waiting for approvaltempo_get_timesheet_approvals_by_team(teamId, from, to?, view?)Get every team member's approval for a periodtempo_get_timesheet_reviewers(accountId, view?)List who can review a user's timesheettempo_search_timesheet_approval_logs(..., view?)Search approval audit logstempo_submit_timesheet(accountId, from, to?, ...)Submit a timesheet for approvaltempo_approve_timesheet(accountId, from, to?, ...)Approve a submitted timesheettempo_reject_timesheet(accountId, from, to?, ...)Reject a submitted timesheettempo_reopen_timesheet(accountId, from, to?, ...)Reopen an approved timesheettempo_recall_timesheet(accountId, from, to?, ...)Recall your own unapproved timesheettempo_get_periods(from, to, view?)Get Tempo period definitionstempo_get_user_schedule(accountId, from, to, view?)Get a user's work scheduletempo_get_global_configuration(view?)Get global Tempo settingstempo_get_work_attributes(view?)List custom worklog attributestempo_get_roles(view?)List all Tempo rolestempo_healthcheck()Is this connector working? Reports which credential resolved, whether api.tempo.io accepted it, and what to fix. Start here when another tool fails — an empty result can mean "no data" or "never authenticated", and this separates them.
view)#Every read tool takes view: "compact" | "full", and compact is the
default — you get the slim rung without asking for it. That is 30 of this
server's 48 tools; the seventeen confirmation-gated writes and tempo_healthcheck
have no view.
Compact here is media stripping, not a field projection, and the
difference is the thing to know before you rely on it. src/view.ts says so
outright: this repo holds no captured Tempo payload and no documented field
list, so nothing in it can honestly claim to know which of Tempo's fields
matter and which are noise. Compact therefore does the one projection that
needs no such knowledge — it removes keys whose value is a picture ( avatar,
picture, photo, icon, logo, and their Url / Uri / Link forms)
along with bare image URLs. That is SUBTRACTIVE, so it cannot lose a field
nobody knew about, which is what an invented field list would have risked: a
worklog coming back with holes in it and reading like a verified answer.
The surprise to expect is that compact often changes nothing. Tempo is a
time-tracking API — worklogs, plans, periods, approval logs — and a payload
with no picture in it comes back byte-identical on both rungs. So do not read
a short response as evidence that fields were withheld, and do not reach for
full hoping a field you wanted is hiding behind it. If it is not in compact
and it is not an image URL, Tempo did not send it.
view: "full" returns Tempo's payload untouched. There is deliberately no
raw rung: nothing here re-serialises or normalises a response, so full
already IS the upstream payload, and a third value would silently alias one
that exists.
The tools without view have it for two distinct reasons, neither of them an
oversight:
tempo_create_* / tempo_update_* /
tempo_delete_* plus submit / approve / reject / reopen / recall
— answer with a receipt: a confirmation preview, or an id and a status. There is
nothing in a receipt to strip and everything in it to keep.tempo_healthcheck returns a diagnostic verdict — which credential
resolved, whether api.tempo.io accepted it, what to fix. Same reasoning,
and it is the one read-only tool in that group.Passing view to one of those is not an error and does not fail: the tool
does not declare it, so zod drops the unknown key and the call runs exactly as
it would have. You get no warning, so do not treat a successful call as
evidence the rung was honoured.
Log time for today:
text
tempo_create_worklog(authorAccountId, issueId, startDate: "today", timeSpentSeconds: 3600)
See this week's time for a user:
text
tempo_get_worklogs_by_user(accountId, from: "2026-03-16", to: "2026-03-20")
Check resource plan for a project:
text
tempo_get_plans(from: "2026-03-01", to: "2026-03-31", projectIds: [123])
Find all worklogs for an issue:
text
tempo_get_worklogs_by_issue(issueId: 456, from: "2026-01-01")
Review pending timesheet approvals:
text
tempo_get_timesheet_approvals_waiting()
tempo_get_timesheet_approval_status(accountId, from: "2026-03-01", to: "2026-03-31")
Act on a timesheet (all five actions ask the user to confirm first — see Confirmations below):
text
tempo_get_periods(from: "2026-03-01", to: "2026-03-31") # find the period boundaries
tempo_approve_timesheet(accountId, from: "2026-03-01", to: "2026-03-31", comment: "LGTM")
# → on a client without confirmation prompts: status "confirmation-required", a preview, and a confirmToken
tempo_approve_timesheet(accountId, from: "2026-03-01", to: "2026-03-31", comment: "LGTM", confirmToken: "<token>")
Chase a team's outstanding timesheets for a period:
text
tempo_get_timesheet_approvals_by_team(teamId: 42, from: "2026-03-01", to: "2026-03-31")
tempo_get_timesheet_reviewers(accountId) # who to route a submission to
Every write — each tempo_create_* / tempo_update_* / tempo_delete_* and the
five timesheet actions — asks the user to confirm before it changes anything.
A client that can show a confirmation prompt (Claude Code) shows one, and the
write runs once the user accepts. A client that cannot (claude.ai, Claude
Desktop) gets two steps instead: the first call does nothing and returns
status: "confirmation-required", a preview of exactly what would be sent
(method, path, willSend body, willSendQuery), and a confirmToken; only a
repeat call with the same arguments plus that confirmToken performs the write.
With MCP_CONFIRM_ELICITATION=off (needed on opencode v2, which never shows
the prompt) every client gets the two steps.
MCP_CONFIRM_MODE=ask-user, show the user the preview and
get their approval in chat before making the second call.TOKEN_REUSED; changing any argument — or, for an update, the resource
being edited upstream in between — fails with DRAFT_CHANGED and returns a
fresh preview and token.MCP_CONFIRM_MODE=refuse, writes are refused on such clients
( reason: "confirmation-unsupported").timeSpentSeconds is always an integer (e.g. 3600 = 1 hour, 1800 = 30 min)authorAccountId is the Atlassian account id (not a username) — required for all worklog operationstempo_get_plans requires both from and to — no other filter is mandatorytempo_get_periods requires both from and to; tempo_get_timesheet_approval_status requires from ( to optional) — the API rejects these calls without a periodoffset + limit to page through resultstempo_get_account takes the numeric id, while update and delete take the string key. Resolve a key to an id with tempo_search_accounts(keys: ["ACCOUNT-123"])tempo_delete_worklog is a hard delete — there is no restorefrom (required) + to (optional) — they apply to a whole period, not an individual worklog. submit/ recall are the timesheet owner's actions; approve/ reject/ reopen require reviewer permissionsrecall pulls back a timesheet that is still waiting for approval; reopen undoes an approval that already went throughBy using this MCP server, you acknowledge and agree to the following:
1. This server accesses your own Tempo account via Tempo's official API. Auth happens via your own per-user OAuth/API token, issued by your Tempo/Jira instance. It does not — and cannot — access anyone else's worklogs or your colleagues' time entries.
2. Tempo's Terms of Use govern your use of this server. The clauses most relevant here:
Your registration is solely for your personal use, and you shall not authorize others to use your account.
And: users must not "automate the use of the Service, such as by using scripts" — except via documented APIs (Section 5.3.2(v)). API tokens are the sanctioned automation mechanism — that's what this server uses.
You are agreeing to those terms — read by the maintainer 2026-05-23 — every time you invoke a tool in this server.
3. Personal, single-user use only. This project is not affiliated with, endorsed by, sponsored by, or in partnership with Tempo Software ehf or Atlassian. It is a personal automation tool for one Tempo-licensed user to drive their own worklogs and reports. Do not use it to log time on behalf of colleagues, to bulk-export reports across an org for resale, or to share your token with anyone else.
4. Your token is yours alone. Tempo issues per-user OAuth/API tokens; do not commit TEMPO_API_TOKEN to git, do not paste it in shared chats, and rotate it if it's ever exposed.
5. Your employer's policy may add restrictions. Tempo is typically licensed via Jira to an organization. Your employer may have IT/security/acceptable-use policies that further restrict scripted automation against Jira/Tempo — even when Tempo's own ToU allows it. Check with your employer's IT/Jira admin before automating against a corporate Tempo instance.
6. You accept full responsibility for any consequences of using this server in connection with your Tempo account — rate limiting, token revocation, account warnings, your IT admin emailing you, or any enforcement action. If Tempo or your employer objects to your use, stop using this server.
This section is the maintainer's good-faith summary of the terms — it is not legal advice and does not modify or supersede Tempo's actual ToU or your employer's policies.