tempo-mcp-server
MCP server for managing Tempo worklogs in Jira
Install / Use
claude mcp add ivelin-web -- npx -y github:ivelin-web/tempo-mcp-serverIf the server publishes to npm under a different name, use that package instead — check the repo README.
MCP Server
Model Context Protocol server
Quality Score
Category
AutomationSupported Platforms
Skill content
View source on GitHubTempo MCP Server
A Model Context Protocol (MCP) server for managing Tempo worklogs in Jira. This server provides tools for tracking time and managing worklogs through Tempo's API, making it accessible through Claude, Cursor and other MCP-compatible clients.
Features
- Retrieve Worklogs: Get all worklogs for a specific date range
- Create Worklog: Log time against Jira issues
- Bulk Create: Create multiple worklogs in a single operation
- Edit Worklog: Modify time spent, dates, and descriptions
- Delete Worklog: Remove existing worklogs
- Missing Days Report: Find working days where you logged less than expected (uses Tempo's user-schedule, so holidays and non-working days are skipped automatically)
- Worklog Analytics: Aggregate hours by issue, account, day, week, or month with totals and percentages
System Requirements
- Node.js 18+ (LTS recommended) — only needed for the local stdio modes
- Jira Cloud instance
- Tempo API token
- Jira API token (not required when using OAuth 2.0 PKCE authentication)
Usage Options
There are three ways to use this MCP server:
- Remote / Cloudflare Workers (no install) — host once, share with your team. Each user generates their own URL via a setup page and pastes it into Claude.ai or ChatGPT. Works from web and mobile.
- NPX: Run directly with
npxon your laptop, no clone required. - Local Clone: Clone the repository for development or customization.
If you just want to use the server, option 1 is the easiest and works on phones too. If you're a maintainer deploying for your team, see the Remote deployment guide.
Option 1: Remote (Cloudflare Workers)
For end users
Once your team has the server deployed, the flow is:
- Open
https://<your-deployment>.workers.dev/setup. - Paste your Tempo API token, Jira base URL, Jira API token, and Jira email. Hit Generate MCP URL.
- The page returns a personal URL like
https://<your-deployment>.workers.dev/mcp/u_<random>. Copy it. - In Claude.ai → Settings → Connectors → Add custom connector, paste the URL.
- The connector syncs across web, desktop, and mobile (iOS/Android).
For ChatGPT: enable Settings → Apps → Advanced → Developer mode (Pro/Plus/Business+), then add the URL as a custom MCP server. Plus/Pro accounts can read; write tools (create/edit worklogs) require Business+ per OpenAI's tier.
The URL contains your credentials — treat it like a password, don't share or commit it.
Remote deployment (Cloudflare Workers)
Free-tier hosting on Cloudflare Workers. ~5–10 minutes from clone to live URL. Anyone can fork and self-host — no upstream coordination needed.
Prerequisites
- A Cloudflare account (free plan is enough).
- Node.js 18+ and
npmlocally — only used forwranglerCLI; the Worker runtime itself doesn't run Node.
One-time setup
git clone https://github.com/ivelin-web/tempo-mcp-server.git
cd tempo-mcp-server
npm install
# 1. Log in to Cloudflare (opens browser).
npx wrangler login
# 2. Create your own KV namespace for per-user credentials.
npx wrangler kv namespace create USERS
⚠️ If you forked the repo: the committed
wrangler.jsonckv_namespaces[0].idbelongs to the upstream maintainer's Cloudflare account. Replace it with the id step 2 just returned, otherwisewrangler deploywill fail withKV namespace … is not valid. KV namespace ids are public per-account identifiers, not secrets, but each account has its own.
# 3. Generate and store the encryption key.
# Used to AES-GCM-encrypt per-user credentials in KV.
openssl rand -base64 48 | npx wrangler secret put ENCRYPTION_KEY
# 4. (Optional) Pin the CORS origin. Defaults to "*". Set it if you only
# want browsers from a specific app to call the Worker.
echo "https://claude.ai" | npx wrangler secret put ALLOWED_ORIGIN
# 5. Deploy.
npm run remote:deploy
# → outputs https://tempo-mcp-server.<your-account>.workers.dev
Visit /setup on the deployed URL to onboard your first user.
Updating an existing deployment
After pulling new commits from upstream:
npm install # picks up any new deps
npm run remote:deploy # ships the new Worker bundle
Secrets and KV data persist across deploys. compatibility_date and compatibility_flags in wrangler.jsonc are pinned, so behaviour doesn't drift silently when Cloudflare ships runtime changes.
Local development
cp .dev.vars.example .dev.vars
# edit .dev.vars and put a real ENCRYPTION_KEY (any value works locally)
npm run remote:dev
# → http://localhost:8787 with a mock KV; data is wiped between sessions
Other useful scripts:
npm run remote:typecheck— type-check the Worker bundle (usestsconfig.worker.json).npm run remote:tail— stream live logs from the deployed Worker.
Troubleshooting
KV namespace … is not valid—kv_namespaces[0].idinwrangler.jsoncis empty (or wrong). Runnpx wrangler kv namespace create USERSand paste the new id.ENCRYPTION_KEY is not definedat runtime — secret wasn't set. Re-run step 3.Rate limit binding … not available— your account's plan doesn't include the Workers Rate Limiting API. Either upgrade, or remove theratelimitsblock inwrangler.jsoncand theSETUP_RATE_LIMITER.limit(...)call insrc/remote/worker.ts.- 404 from
/mcp/u_…— the user id is unknown (or never existed). The Worker returns 404 by design for invalid/missing ids; have the user re-run/setup. - Existing users suddenly can't connect — most likely cause is a rotated
ENCRYPTION_KEY; existing AES-GCM blobs can't be decrypted with the new key. See the warning below.
How it works
Credential storage: the /setup POST handler AES-GCM encrypts the form data with ENCRYPTION_KEY and stores it in KV under user:u_<random>. Each MCP request reads + decrypts that record, builds an McpServer for that single request, and dispatches via Cloudflare's official createMcpHandler. No credentials are held in memory between requests; no Durable Objects are used.
Treat
ENCRYPTION_KEYas long-lived. Rotating it invalidates every existing user record (the AES-GCM tag won't validate against the new key), and all your users will need to re-run/setup. Pick a key fromopenssl rand -base64 48once and never change it.
Auth model: the URL /mcp/u_<id> is the credential. The 22-char base64url id carries ~128 bits of entropy. We never return 401 for that path (Claude.ai web has known bugs around the 401-then-OAuth flow), and we return 404 for unknown ids. This matches the URL-token pattern used by Zapier MCP, Pipedream MCP, and similar.
Hardening already in place:
- Per-IP rate limit (5 req/min) on
POST /setup, via Cloudflare's native Rate Limiting binding. Cache-Control: no-storeon/setupresponses so the success page (which contains the MCP URL) and the error re-render (which echoes tokens back) never sit in any cache.Referrer-Policy: no-referreron every HTML page so the MCP URL doesn't leak via referrer headers.
Limits to know about:
- Workers free plan: 100k requests/day, 50ms CPU per request (we are I/O-bound, comfortable).
- KV free plan: 100k reads/day, 1k writes/day. Setup writes once per user; reads happen per MCP call.
- The Worker only supports Jira basic auth (classic API token + email). Bearer and the OAuth 2.0 PKCE flow are stdio-only — bearer requires gateway URL routing that the Worker does not yet do, and PKCE needs a browser callback the Worker can't host.
Option 2: NPX Usage
The easiest way to use this server is via npx without installation:
Connecting to Claude Desktop (NPX Method)
-
Open your MCP client configuration file:
- Claude Desktop (macOS):
~/Library/Application Support/Claude/claude_desktop_config.json - Claude Desktop (Windows):
%APPDATA%\Claude\claude_desktop_config.json
- Claude Desktop (macOS):
-
Add the following configuration:
{
"mcpServers": {
"Jira_Tempo": {
"command": "npx",
"args": ["-y", "@ivelin-web/tempo-mcp-server"],
"env": {
"TEMPO_API_TOKEN": "your_tempo_api_token_here",
"JIRA_API_TOKEN": "your_jira_api_token_here",
"JIRA_EMAIL": "your_email@example.com",
"JIRA_BASE_URL": "https://your-org.atlassian.net"
}
}
}
}
- Restart your Claude Desktop client
One-Click Install for Cursor
Option 3: Local Repository Clone
Installation
# Clone the repository
git clone https://github.com/ivelin-web/tempo-mcp-server.git
cd tempo-mcp-server
# Install dependencies
npm install
# Build TypeScript files
npm run build
Running Locally
There are two ways to run the server locally:
1. Using the MCP Inspector (for development and debugging)
npm run inspect
2. Using Node directly
You can run the server directly with Node by pointing to the built JavaScript file:
Connecting to Claude Desktop (Local Method)
- Open your MCP client configuration file
- Add the following configuration:
{
"mcpServers": {
"Jira_Tempo": {
"command": "node",
"args": ["/ABSOLUTE/PATH/TO/tempo-mcp-server/build/index.js"],
"env": {
"TEMPO_API_TOKEN": "your_tempo_api_token_here",
"JIRA_API_TOKEN": "your_jira_api_token_here",
"JIRA_EMAIL": "your_email@example.com",
"JIRA_BASE_URL": "https://your-org.atlassian.net"
}
}
}
}
- Restart your Claude Desktop client
Getting API Tokens
-
Tempo API Token:
- Go to Tempo > Settings > API Integration
- Create a new API token with Custom access and select at minimum:
- Worklogs (View + Manage) — for all worklog tools
- Schemes (View) — required for
getMissingWorklogDays(reads the user-schedule) - Accounts (View) — only if your worklogs use Tempo accounts
- Teams (View) — only if you use the
program/teamfilters (covers Teams and Programs)
- Tempo does not allow editing scopes on an existing token; create a new one if you need to add scopes later.
-
Jira API Token:
- Go to Atlassian API tokens
- Click "Create API token" (the classic, unscoped flow). This is what works with
basicauth out of the box. - Do not use "Create API token with scopes" — those tokens must be sent through Atlassian's gateway URL (
https://api.atlassian.com/ex/jira/{cloudId}/...) with the cloud ID, which this server'sbasicauth path does not currently route to. They will fail with 401 against your site URL. If you only have a scoped token available (e.g. your org disabled classic tokens), use the OAuth 2.0 PKCE flow instead — it routes through the gateway automatically.
Environment Variables
The server requires the following environment variables:
TEMPO_API_TOKEN # Your Tempo API token
JIRA_API_TOKEN # Your Jira API token (required for basic an
Truncated for display — read the full file on GitHub.
Related Skills
Agent-Reach
84.2kGive your AI agent eyes to see the entire internet. Read & search Twitter, Reddit, YouTube, GitHub, Bilibili, XiaoHongShu — one CLI, zero API fees.
headroom
73.4kCompress tool outputs, logs, files, and RAG chunks before they reach the LLM. 20% fewer tokens for coding agents, 60-95% fewer tokens for JSON, same answers. Library, proxy, MCP server.
ruflo
73.0k🌊 The original agent harness. Deploy intelligent multi-player swarms, coordinate autonomous workflows, and build conversational AI systems. Features adaptive memory, self-learning intelligence, federation, vector RAG integration, and native Claude Code / Codex / Hermes and many more Integrated
CowAgent
47.1kOpen-source super AI assistant & Agent Harness. Plans tasks, runs tools and skills, self-evolves with memory and knowledge. Multi-agent, multi-model, multi-channel. Lightweight, extensible, one-line install.

