关于 Tempo MCP Server
Tempo MCP Server 用于在 Jira 中管理 Tempo 工时记录,可通过 Claude、Cursor 等 MCP 客户端完成记录、编辑、删除和统计。适合需要通过 AI 处理工时的 Jira 用户,支持远程和本地两种运行方式。
主要功能
- 01查询指定日期范围的工时记录
- 02创建、批量创建、编辑和删除工时
- 03按工作日检查缺失的工时记录
- 04按问题、账户、日期等维度汇总工时
- 05支持 Cloudflare Workers 远程部署
适用场景
- 01通过对话为 Jira 问题补录工时
- 02批量导入一段时间内的工时记录
- 03检查一周或一月内未填写工时的工作日
MCP 相关
该项目是 MCP 服务,向 Claude、Cursor 等 MCP 客户端暴露 Tempo 工时相关的工具,并通过 Tempo 与 Jira API 执行操作。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
Tempo MCP 服务
用于在 Jira 中管理 Tempo 工时记录的模型上下文协议(MCP)服务。此服务通过 Tempo 的 API 提供时间跟踪和工时记录管理工具,可通过 Claude、Cursor 和其他兼容 MCP 的客户端使用。
功能
- 获取工时记录:获取指定日期范围内的所有工时记录
- 创建工时记录:为 Jira 问题记录工时
- 批量创建:在单次操作中创建多条工时记录
- 编辑工时记录:修改耗时、日期和描述
- 删除工时记录:移除现有工时记录
- 缺勤日报告:查找记录工时少于预期的工作日(使用 Tempo 的用户日程,因此会自动跳过节假日和非工作日)
- 工时记录分析:按问题、账户、日、周或月汇总工时,并显示总计和百分比
系统要求
- Node.js 18+(建议使用 LTS)——仅本地 stdio 模式需要
- Jira Cloud 实例
- Tempo API 令牌
- Jira API 令牌(使用 OAuth 2.0 PKCE 身份验证时不需要)
使用选项
有三种方式可以使用此 MCP 服务:
- 远程 / Cloudflare Workers(无需安装)——部署一次,与团队共享。每位用户都可通过设置页面生成自己的 URL,并将其粘贴到 Claude.ai 或 ChatGPT。支持网页端和移动端。
- NPX:在笔记本电脑上直接通过
npx运行,无需克隆。 - 本地克隆:克隆仓库以进行开发或自定义。
如果你只想使用此服务,选项 1 最简单,而且也支持手机。如果你是要为团队部署的维护者,请参阅远程部署指南。
选项 1:远程(Cloudflare Workers)
面向最终用户
团队部署好服务后,使用流程如下:
- 打开
https://<your-deployment>.workers.dev/setup。 - 粘贴你的 Tempo API 令牌、Jira 基础 URL、Jira API 令牌和 Jira 邮箱。点击生成 MCP URL。
- 页面会返回一个个人 URL,例如
https://<your-deployment>.workers.dev/mcp/u_<random>。复制该 URL。 - 在Claude.ai → Settings → Connectors → Add custom connector 中粘贴该 URL。
- 连接器会在网页端、桌面端和移动端(iOS/Android)之间同步。
对于 ChatGPT:启用 Settings → Apps → Advanced → Developer mode(Pro/Plus/Business+),然后将该 URL 添加为自定义 MCP 服务。Plus/Pro 账户可以读取;根据 OpenAI 的套餐规定,写入工具(创建/编辑工时记录)需要 Business+。
URL 中包含你的凭据——请像对待密码一样妥善保管,不要分享或提交。
远程部署(Cloudflare Workers)
Cloudflare Workers 提供免费套餐托管。从克隆到获得可用 URL 大约需要 5–10 分钟。任何人都可以复刻并自行托管,无需与上游协调。
先决条件
- Cloudflare 账户(免费套餐即可)。
- 本地安装 Node.js 18+ 和
npm——仅用于wranglerCLI;Worker 运行时本身不运行 Node。
一次性设置
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
⚠️ 如果你复刻了此仓库: 已提交的
wrangler.jsonc中的kv_namespaces[0].id属于上游维护者的 Cloudflare 账户。请将其替换为步骤 2 刚刚返回的 id,否则wrangler deploy会因KV namespace … is not valid而失败。KV 命名空间 ID 是每个账户公开的标识符,并非机密,但每个账户都有自己的 ID。
# 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
访问已部署 URL 上的 /setup,为第一位用户完成设置。
更新现有部署
从上游拉取新提交后:
npm install # picks up any new deps
npm run remote:deploy # ships the new Worker bundle
密钥和 KV 数据会在各次部署之间保留。wrangler.jsonc 中的 compatibility_date 和 compatibility_flags 已固定,因此 Cloudflare 发布运行时变更时,行为不会悄然改变。
本地开发
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
其他实用脚本:
npm run remote:typecheck— 对 Worker 程序包进行类型检查(使用tsconfig.worker.json)。npm run remote:tail— 实时流式查看已部署 Worker 的日志。
故障排除
KV namespace … is not valid—wrangler.jsonc中的kv_namespaces[0].id为空(或错误)。运行npx wrangler kv namespace create USERS,并粘贴新 ID。- 运行时出现
ENCRYPTION_KEY is not defined— 未设置密钥。重新执行第 3 步。 Rate limit binding … not available— 你的账户套餐不包含 Workers Rate Limiting API。请升级套餐,或移除wrangler.jsonc中的ratelimits块,以及src/remote/worker.ts中的SETUP_RATE_LIMITER.limit(...)调用。/mcp/u_…返回 404 — 用户 ID 未知(或从未存在)。对于无效或缺失的 ID,Worker 会按设计返回 404;请让用户重新运行/setup。- 现有用户突然无法连接 — 最可能的原因是
ENCRYPTION_KEY已轮换;现有 AES-GCM 数据块无法用新密钥解密。请参阅下方警告。
工作原理
凭据存储:/setup POST 处理程序使用 ENCRYPTION_KEY 对表单数据进行 AES-GCM 加密,并将其存储在 KV 的 user:u_<random> 项下。每个 MCP 请求都会读取并解密该记录,为该请求单独构建一个 McpServer,再通过 Cloudflare 官方的 createMcpHandler 进行分发。请求之间不会在内存中保留凭据;也不会使用 Durable Objects。
请将
ENCRYPTION_KEY视为长期密钥。 轮换它会使所有现有用户记录失效(新的密钥无法验证 AES-GCM 标签),所有用户都需要重新运行/setup。运行一次openssl rand -base64 48生成密钥,并且永远不要更改它。
**身份验证模式:**URL /mcp/u_<id> 本身就是 凭据。这个 22 个字符的 base64url ID 具有约 128 位熵。我们绝不会对该路径返回 401(Claude.ai 网页版在 401 后接 OAuth 的流程中存在已知问题),未知 ID 则返回 404。这与 Zapier MCP、Pipedream MCP 及类似服务使用的 URL 令牌模式一致。
已实施的安全加固:
- 对
POST /setup按 IP 限制请求速率(每分钟 5 次),通过 Cloudflare 原生 Rate Limiting 绑定实现。 - 对
/setup响应设置Cache-Control: no-store,确保成功页面(包含 MCP URL)和重新渲染的错误页面(会回显令牌)不会存入任何缓存。 - 对每个 HTML 页面设置
Referrer-Policy: no-referrer,避免 MCP URL 通过引荐来源标头泄露。
需要了解的限制:
- Workers 免费套餐:每天 100k 次请求,每次请求 50ms CPU 时间(我们的工作受 I/O 限制,余量充足)。
- KV 免费套餐:每天 100k 次读取、1k 次写入。每位用户只在设置时写入一次;每次 MCP 调用都会读取。
- Worker 仅支持 Jira basic 身份验证(经典 API 令牌 + 电子邮件)。Bearer 和 OAuth 2.0 PKCE 流程仅支持 stdio 模式——Bearer 需要 Worker 尚未实现的网关 URL 路由,而 PKCE 需要 Worker 无法托管的浏览器回调。
选项 2:NPX 用法
使用此服务最简单的方式是通过 npx,无需安装:
连接到 Claude Desktop(NPX 方式)
-
打开 MCP 客户端配置文件:
- Claude Desktop(macOS):
~/Library/Application Support/Claude/claude_desktop_config.json - Claude Desktop(Windows):
%APPDATA%\Claude\claude_desktop_config.json
- Claude Desktop(macOS):
-
添加以下配置:
{
"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": "[email protected]",
"JIRA_BASE_URL": "https://your-org.atlassian.net"
}
}
}
}
- 重启 Claude Desktop 客户端
Cursor 一键安装
选项 3:克隆本地仓库
安装
# 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
在本地运行
在本地运行服务有两种方式:
1. 使用 MCP Inspector(用于开发和调试)
npm run inspect
2. 直接使用 Node
你可以直接使用 Node 运行服务,指定构建后的 JavaScript 文件:
连接到 Claude Desktop(本地方式)
- 打开 MCP 客户端配置文件
- 添加以下配置:
{
"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": "[email protected]",
"JIRA_BASE_URL": "https://your-org.atlassian.net"
}
}
}
}
- 重启 Claude Desktop 客户端
获取 API 令牌
-
Tempo API 令牌:
- 前往 Tempo > Settings > API Integration
- 创建一个具有 Custom access 的新 API 令牌,并至少选择以下权限:
- Worklogs(View + Manage)——用于所有工时日志工具
- Schemes(View)——
getMissingWorklogDays所需(读取用户日程) - Accounts(View)——仅当你的工时日志使用 Tempo 账户时需要
- Teams(View)——仅当你使用
program/team筛选条件时需要(涵盖 Teams 和 Programs)
- Tempo 不允许修改现有令牌的权限范围;如果之后需要添加权限范围,请创建新令牌。
-
Jira API 令牌:
- 前往 Atlassian API 令牌
- 点击 “Create API token”(经典的、无权限范围的流程)。这是开箱即用的
basic身份验证方式。 - 不要使用 “Create API token with scopes”——此类令牌必须通过 Atlassian 网关 URL(
https://api.atlassian.com/ex/jira/{cloudId}/...)并附带云 ID 发送,而此服务目前的basic身份验证路径不会将请求路由到该网关。使用此类令牌访问你的网站 URL 会收到 401 错误。如果你只能使用带权限范围的令牌(例如,你的组织禁用了经典令牌),请改用 OAuth 2.0 PKCE 流程——它会自动通过网关路由。
环境变量
服务需要以下环境变量:
TEMPO_API_TOKEN # Your Tempo API token
JIRA_API_TOKEN # Your Jira API token (required for basic and bearer auth)
JIRA_EMAIL # Your Jira account email (required for basic auth)
JIRA_BASE_URL # Your Jira instance URL (e.g., https://your-org.atlassian.net)
JIRA_AUTH_TYPE # Optional: 'basic' (default), 'bearer', or 'oauth'
JIRA_OAUTH_CLIENT_ID # OAuth 2.0 client ID (required for oauth auth)
JIRA_OAUTH_CLIENT_SECRET # OAuth 2.0 client secret (required for oauth auth)
JIRA_TEMPO_ACCOUNT_CUSTOM_FIELD_ID # Optional: Custom field ID for Tempo accounts
你可以在环境中设置这些变量,或在 MCP 客户端配置中提供它们。
身份验证类型
服务支持三种 Jira API 身份验证方式:
基本身份验证(默认)
使用电子邮件地址和 API 令牌。这是传统方式:
{
"env": {
"JIRA_API_TOKEN": "your_api_token",
"JIRA_EMAIL": "[email protected]",
"JIRA_AUTH_TYPE": "basic"
}
}
Bearer 令牌身份验证(OAuth 2.0)
适用于希望使用 OAuth 2.0 带权限范围令牌以增强安全性的用户:
{
"env": {
"JIRA_API_TOKEN": "your_oauth_access_token",
"JIRA_AUTH_TYPE": "bearer"
}
}
注意:使用 bearer 身份验证时,不需要 JIRA_EMAIL,因为用户身份由令牌确定。
OAuth 2.0 PKCE 身份验证
某些 Atlassian 组织会通过管理员策略限制 API 令牌访问,导致基本身份验证和 Bearer 身份验证失败。oauth 类型实现了完整的 OAuth 2.0 PKCE 授权码流程,无论 API 令牌访问是否受限都能正常工作——令牌有效期较短,并会自动刷新,无需手动管理。
首次使用时,会打开浏览器窗口供你授权访问。令牌会在本地保存到 ~/.tempo-mcp-server/tokens.json,并自动刷新。
-
在 Atlassian Developer Console 中创建 OAuth 2.0 应用,设置
read:jira-user和read:jira-work权限范围,并将http://localhost:7788/callback设为回调 URL。 -
配置服务:
{
"env": {
"JIRA_BASE_URL": "https://your-org.atlassian.net",
"JIRA_AUTH_TYPE": "oauth",
"JIRA_OAUTH_CLIENT_ID": "your_client_id",
"JIRA_OAUTH_CLIENT_SECRET": "your_client_secret"
}
}
注意:使用 oauth 身份验证时,不需要 JIRA_API_TOKEN 和 JIRA_EMAIL。
Tempo 账户配置
如果您的 Tempo 实例要求工作日志关联到账户,请设置包含账户信息的自定义字段 ID:
JIRA_TEMPO_ACCOUNT_CUSTOM_FIELD_ID=10234
查找自定义字段 ID:
- 前往 Jira Settings → Issues → Custom Fields
- 找到 Tempo 账户字段,并从 URL 或字段配置中记下 ID
查看其他用户的工作日志
读取工具(retrieveWorklogs、getWorklogAnalytics、getMissingWorklogDays)默认读取令牌所有者自己的工作日志,但也接受可选筛选条件来指定其他人员,这对管理员、项目经理和团队负责人很有用:
users— 电子邮件地址、显示名称或 Jira accountId 数组(例如["[email protected]", "Maria Petrova"])program— Tempo Program 名称或 ID;扩展为该 Program 各团队的所有当前成员team— Tempo Team 名称或 ID;扩展为该 Team 的所有当前成员
筛选条件按并集组合。Tempo 会在服务端强制执行权限:API 会静默省略令牌所有者无权查看的工作日志(不会返回错误)。若要查看其他用户的信息,您需要:
- 为令牌所有者授予 View Worklogs 权限的 Tempo Permission Role(Tempo > Settings > Permission Roles)——为所有人选择“Full”,或选择“Restricted”并指定团队
- 对相关项目拥有 Jira Browse Projects 权限
- 如果使用
program/team筛选条件,Tempo API 令牌需要 Teams 范围
getWorklogAnalytics 还支持 groupBy: "user"——与 program 搭配使用,可通过单次调用生成每人工作时长报告。使用筛选条件调用 getMissingWorklogDays 时,会返回每位用户缺少工时的日期报告(查看其他用户的日程同样受权限限制)。
可用工具
retrieveWorklogs
获取已配置用户(或通过筛选条件指定的其他用户)在开始日期和结束日期之间的工作日志。
Parameters:
- startDate: String (YYYY-MM-DD)
- endDate: String (YYYY-MM-DD)
- users: String[] (optional) — emails, display names, or accountIds
- program: String (optional) — Tempo Program name or id
- team: String (optional) — Tempo Team name or id
createWorklog
为特定 Jira 问题创建新的工作日志。
Parameters:
- issueKey: String (e.g., "PROJECT-123")
- timeSpentHours: Number (positive)
- date: String (YYYY-MM-DD)
- description: String (optional)
- startTime: String (HH:MM format, optional)
bulkCreateWorklogs
通过单次操作创建多条工作日志。
Parameters:
- worklogEntries: Array of {
issueKey: String
timeSpentHours: Number
date: String (YYYY-MM-DD)
description: String (optional)
startTime: String (HH:MM format, optional)
}
editWorklog
修改现有工作日志。
Parameters:
- worklogId: String
- timeSpentHours: Number (positive)
- description: String (optional)
- date: String (YYYY-MM-DD, optional)
- startTime: String (HH:MM format, optional)
deleteWorklog
删除现有工作日志。
Parameters:
- worklogId: String
getMissingWorklogDays
报告日期范围内用户记录工时少于预期的工作日。每日预期工时取自用户的 Tempo 日程,因此会自动考虑节假日、非工作日和兼职日程。使用 users / program / team 可检查其他人员,并返回按缺少工时从多到少排序的逐用户报告。
Parameters:
- startDate: String (YYYY-MM-DD)
- endDate: String (YYYY-MM-DD)
- minHoursPerDay: Number (optional) — override the per-day threshold;
non-working days are still skipped
- users: String[] (optional) — emails, display names, or accountIds
- program: String (optional) — Tempo Program name or id
- team: String (optional) — Tempo Team name or id
所需 Tempo 范围: 除 Worklogs 外,
TEMPO_API_TOKEN还必须包含 Schemes 范围(涵盖 Workload Schemes、Holiday Schemes、User Schedule)。Tempo 不允许修改现有令牌的范围——如果您当前的令牌只有 Worklogs,请前往 Tempo > Settings > API Integration 创建新令牌。
getWorklogAnalytics
汇总日期范围内的工作日志,并按工时降序返回各组的工时、工作日志数量和百分比。将 groupBy: "user" 与 program / team / users 搭配使用,可生成逐人员报告。
Parameters:
- startDate: String (YYYY-MM-DD)
- endDate: String (YYYY-MM-DD)
- groupBy: "issue" | "account" | "user" | "day" | "week" | "month" (optional, default "issue")
- users: String[] (optional) — emails, display names, or accountIds
- program: String (optional) — Tempo Program name or id
- team: String (optional) — Tempo Team name or id
项目结构
tempo-mcp-server/
├── src/ # Source code
│ ├── authors.ts # Author filter resolution (users/program/team → accountIds)
│ ├── config.ts # Configuration management
│ ├── index.ts # MCP server implementation
│ ├── jira.ts # Jira API integration
│ ├── oauth.ts # OAuth 2.0 PKCE flow and token management
│ ├── tools.ts # Tool implementations
│ ├── types.ts # TypeScript types and schemas
│ └── utils.ts # Utility functions
├── build/ # Compiled JavaScript (generated)
├── tsconfig.json # TypeScript configuration
└── package.json # Project metadata and scripts
故障排除
如果遇到问题:
- 检查是否已正确设置所有环境变量
- 确认 Jira 和 Tempo API 令牌拥有正确的权限
- 检查控制台输出中的错误消息
- 尝试使用检查器运行:
npm run inspect
许可证
致谢
此服务实现了由 Anthropic 制定的 Model Context Protocol 规范。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。
