A small local MCP server for Jira Cloud worklogs — the piece the Atlassian MCP doesn't cover. Pairs with toggl-mcp to push tracked time into Jira at the end of the day.
| Tool | What it does |
|---|---|
add_worklog |
Log work on an issue (POST /issue/{key}/worklog). |
list_worklogs |
List an issue's worklogs (verify / check for duplicates). |
whoami |
Confirm the configured credentials. |
The Jira quirks are baked in: Basic-auth, the started format yyyy-MM-dd'T'HH:mm:ss.SSSZ (offset without a colon, no bare Z), and ADF-wrapped comments.
- Node.js 18+.
- A Jira API token — create one at https://id.atlassian.com/manage-profile/security/api-tokens.
- Your Atlassian account email and your Jira site URL (e.g.
https://your-site.atlassian.net).
git clone https://github.com/MikeAtPinnacle/jira-worklog-mcp.git
cd jira-worklog-mcp
npm install
npm run buildCompiles to dist/index.js — note its absolute path for the config below.
The server reads three env vars (provide them via the MCP client's env block):
| Var | Example |
|---|---|
JIRA_BASE_URL |
https://your-site.atlassian.net |
JIRA_EMAIL |
you@example.com |
JIRA_API_TOKEN |
(from the link above) |
Auth is HTTP Basic base64(email:api_token) — the server does that for you.
claude mcp add jira-worklog --scope user \
--env JIRA_BASE_URL=https://your-site.atlassian.net \
--env JIRA_EMAIL=you@example.com \
--env JIRA_API_TOKEN=<your_jira_api_token> \
-- node /absolute/path/to/jira-worklog-mcp/dist/index.jsEdit the Claude Desktop config (%APPDATA%\Claude\claude_desktop_config.json on Windows; ~/Library/Application Support/Claude/... on macOS; ~/.config/Claude/... on Linux):
{
"mcpServers": {
"jira-worklog": {
"command": "node",
"args": ["/absolute/path/to/jira-worklog-mcp/dist/index.js"],
"env": {
"JIRA_BASE_URL": "https://your-site.atlassian.net",
"JIRA_EMAIL": "you@example.com",
"JIRA_API_TOKEN": "<your_jira_api_token>"
}
}
}
}add_worklog — started defaults to now; Jira records at minute granularity (min 60s).
{ "issue_key": "LEGLINK-142", "time_spent_seconds": 5400, "started": "2026-06-26T13:00:00Z", "comment": "Code review" }list_worklogs
{ "issue_key": "LEGLINK-142" }whoami — no arguments.
Claude orchestrates the two servers:
toggl-mcp→list_time_entries { start_date, end_date, exclude_tag: "jira-logged" }— each entry hastask_name(the Jira key),start,duration; skip running timers.jira-worklog-mcp→add_worklog { issue_key: task_name, time_spent_seconds: duration, started: start, comment: description }per entry.toggl-mcp→tag_time_entry { time_entry_id, tags: ["jira-logged"] }so the entry isn't logged again.
Because step 1 excludes jira-logged, the whole flow is safe to re-run.
export JIRA_BASE_URL="https://your-site.atlassian.net" # PowerShell: $env:JIRA_BASE_URL="..."
export JIRA_EMAIL="you@example.com"
export JIRA_API_TOKEN="<your_jira_api_token>"
npm run build && npm run smokeA self-cleaning end-to-end worklog test (writes to a real issue, then deletes it — use a throwaway ticket):
npm run worklogtest -- TEST-123- stdio server: logs go to stderr only; stdout is reserved for the MCP protocol.
- Rate limits: 429/5xx are retried with backoff (honoring
Retry-After). - Dedupe is handled on the Toggl side via the
jira-loggedtag;list_worklogsis available if you also want to check the Jira side.