toggl-focus-mcp
MCP server for Toggl Focus 2.0, enabling project, task, and time-entry management with live timer control through natural language.
README
toggl-focus-mcp
MCP server for Toggl Focus (2.0) — not Toggl Track 1.0.
Connect Claude, Cursor, Codex, or OpenCode to your Focus workspace with a Bearer API key (toggl_sk_…) and npx. No OAuth browser flow required.
npx -y toggl-focus-mcp
| Auth | Focus Bearer API key (Authorization: Bearer toggl_sk_…) |
| API | https://focus.toggl.com/api |
| Transport | stdio MCP |
| Node | ≥ 20 (CI / .nvmrc → latest Current) |
Track “API Token” values (Basic Auth / profile token for Track) do not work. Create a Focus / Toggl 2.0 key in settings. Official OAuth MCP:
@togglhq/mcp.
Prerequisites
- A Toggl Focus / 2.0 API key (
toggl_sk_…) — shown once when created - Your organization ID and workspace ID (strongly recommended)
- Node.js 20+ (for
npx)
Find org/workspace IDs in the Focus URL, e.g.
https://focus.toggl.com/.../organizations/21504582/workspaces/21503801/...
Setting both IDs avoids extra discovery calls and protects against Focus hourly quota limits.
Environment variables
| Variable | Required | Description |
|---|---|---|
TOGGL_FOCUS_API_TOKEN |
Yes* | Focus API key (toggl_sk_…) |
TOGGL_API_KEY |
Yes* | Alias for the Focus API key |
TOGGL_API_TOKEN |
Yes* | Additional alias |
TOGGL_ORGANIZATION_ID |
Recommended | Default organization ID |
TOGGL_WORKSPACE_ID |
Recommended | Default workspace ID |
TOGGL_FOCUS_BASE_URL |
No | API base (default https://focus.toggl.com/api) |
* Exactly one of TOGGL_FOCUS_API_TOKEN, TOGGL_API_KEY, or TOGGL_API_TOKEN is required.
Most tools accept optional organization_id / workspace_id arguments that override the env defaults for that call.
Install
Replace toggl_sk_..., 123, and 456 with your real key and IDs.
Claude Code
claude mcp add toggl-focus \
-e TOGGL_FOCUS_API_TOKEN=toggl_sk_... \
-e TOGGL_ORGANIZATION_ID=123 \
-e TOGGL_WORKSPACE_ID=456 \
-- npx -y toggl-focus-mcp
Verify:
claude mcp list
Claude Desktop
Edit claude_desktop_config.json, then restart Claude Desktop.
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"toggl-focus": {
"command": "npx",
"args": ["-y", "toggl-focus-mcp"],
"env": {
"TOGGL_FOCUS_API_TOKEN": "toggl_sk_...",
"TOGGL_ORGANIZATION_ID": "123",
"TOGGL_WORKSPACE_ID": "456"
}
}
}
}
Cursor
Add to project .cursor/mcp.json or your global Cursor MCP settings:
{
"mcpServers": {
"toggl-focus": {
"command": "npx",
"args": ["-y", "toggl-focus-mcp"],
"env": {
"TOGGL_FOCUS_API_TOKEN": "toggl_sk_...",
"TOGGL_ORGANIZATION_ID": "123",
"TOGGL_WORKSPACE_ID": "456"
}
}
}
}
Enable the server in Cursor Settings → MCP, then confirm tools like focus_whoami appear.
Codex
CLI (recommended):
codex mcp add toggl-focus \
--env TOGGL_FOCUS_API_TOKEN=toggl_sk_... \
--env TOGGL_ORGANIZATION_ID=123 \
--env TOGGL_WORKSPACE_ID=456 \
-- npx -y toggl-focus-mcp
Or edit ~/.codex/config.toml (or project .codex/config.toml in a trusted repo):
[mcp_servers.toggl-focus]
command = "npx"
args = ["-y", "toggl-focus-mcp"]
[mcp_servers.toggl-focus.env]
TOGGL_FOCUS_API_TOKEN = "toggl_sk_..."
TOGGL_ORGANIZATION_ID = "123"
TOGGL_WORKSPACE_ID = "456"
To keep secrets out of the file, set them in your shell and forward by name:
[mcp_servers.toggl-focus]
command = "npx"
args = ["-y", "toggl-focus-mcp"]
env_vars = ["TOGGL_FOCUS_API_TOKEN", "TOGGL_ORGANIZATION_ID", "TOGGL_WORKSPACE_ID"]
Shared across Codex CLI, IDE extension, and ChatGPT desktop Codex host. Docs: developers.openai.com/codex/mcp.
OpenCode
Add to opencode.json / opencode.jsonc (project or global):
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"toggl-focus": {
"type": "local",
"command": ["npx", "-y", "toggl-focus-mcp"],
"enabled": true,
"environment": {
"TOGGL_FOCUS_API_TOKEN": "toggl_sk_...",
"TOGGL_ORGANIZATION_ID": "123",
"TOGGL_WORKSPACE_ID": "456"
}
}
}
}
You can also reference shell env vars with OpenCode’s {env:VAR} syntax where supported. Docs: opencode.ai/docs/mcp-servers.
Quick start prompts
Once the server is connected, try:
- “Who am I in Toggl Focus?”
- “List my projects”
- “Start a timer on project X”
- “Create a task called Ship MCP docs on project Y”
- “Show time entries for this week”
Creates, updates, deletes, and timer start/stop apply immediately (no confirmation token).
Tools
24 tools. All are Focus/2.0 only. Shared optional args on almost every tool:
| Arg | Type | Notes |
|---|---|---|
organization_id |
number | Overrides TOGGL_ORGANIZATION_ID |
workspace_id |
number | Overrides TOGGL_WORKSPACE_ID |
page |
number | Default 1 (list tools) |
per_page |
number | Default 50, max 100 (list tools) |
Account & context
focus_whoami
Account metadata + user settings for the authenticated Focus key.
| Arg | Type | Required | Description |
|---|---|---|---|
include_settings |
boolean | No | Default true — also fetch GET /users/me/settings |
organization_id / workspace_id |
number | No | Optional scope |
focus_get_workspace_context
Resolve and cache organization_id / workspace_id for later tools. Prefer setting both env vars. Does not call the session-only /workspaces/{id}/context endpoint (that returns 403 for API keys).
focus_list_org_users
List organization users (assignee lookup). Read-only.
| Arg | Type | Required | Description |
|---|---|---|---|
filter |
string | No | Search name/email |
active_status |
string | No | Active-status filter when supported |
page / per_page |
number | No | Pagination |
Projects
focus_list_projects
List workspace projects.
| Arg | Type | Description |
|---|---|---|
name |
string | Filter by project or client name |
archived / completed / pinned |
boolean | Status filters |
client_id |
number[] | Filter by client IDs |
tag_id |
number[] | Filter by tag IDs |
focus_get_project
| Arg | Type | Required |
|---|---|---|
project_id |
number | Yes |
focus_create_project
Creates immediately. Requires name.
| Arg | Type | Description |
|---|---|---|
name |
string | Required |
description |
string | |
client_id |
number | Supported on create |
color |
string | |
private / pinned / billable |
boolean | |
start_date / end_date |
string | YYYY-MM-DD |
tag_ids |
number[] | Applied via follow-up PATCH; may be forbidden on some plans/roles — project still creates and a warning is returned |
parent_project_id |
number |
focus_update_project
Partial update (PATCH). Requires project_id. Same optional fields as create, plus nullable client_id and optional archived.
Tasks
focus_list_tasks
| Arg | Type | Description |
|---|---|---|
name |
string | Name filter |
project_id |
number[] | Project IDs |
status_id |
number[] | Status IDs |
assignee_user_id |
number[] | Assignees |
tag_id |
number[] | Tags |
pinned / archived |
boolean | |
parent_task_id |
number[] | Parent tasks |
include_assignees |
boolean | Expand assignees |
focus_get_task
Requires task_id. Optional include_assignees.
focus_create_task
Creates immediately. Requires name.
| Arg | Type | Description |
|---|---|---|
name |
string | Required |
description / notes |
string | |
project_id / parent_task_id / status_id |
number | |
assignee_user_ids / tag_ids |
number[] | |
estimated_mins |
number | |
priority |
"none" | "low" | "medium" | "high" |
|
pinned / private / billable |
boolean | |
start_date / end_date |
string | YYYY-MM-DD |
focus_update_task
Partial update. Requires task_id. Same mutable fields as create (all optional).
Live tracking
focus_get_current_timer
Returns the running timer for the workspace, or { "running": false }.
focus_start_timer
Starts immediately. type defaults to "activity".
| Arg | Type | Description |
|---|---|---|
type |
"activity" | "break" |
Default activity |
task_id / project_id |
number | |
description |
string | |
billable |
boolean | |
tag_ids |
number[] | |
time_block_id |
number | |
start |
string | RFC3339; server default = now |
focus_stop_timer
Stops the running timer. Optional end (RFC3339); defaults to current UTC.
Time entries
focus_list_time_entries
Requires a date range. Accepts YYYY-MM-DD or RFC3339 (YYYY-MM-DD is expanded to start/end of day UTC).
| Arg | Type | Required | Description |
|---|---|---|---|
date_from |
string | Yes | Range start |
date_to |
string | Yes | Range end |
task_id |
number | No | |
type |
"activity" | "break" |
No | |
archived / include_taskless |
boolean | No | |
time_block_id |
number | No |
focus_create_time_entry
Creates a completed entry immediately. If task_id is set, uses the task-scoped endpoint; otherwise creates a taskless entry. type defaults to "activity".
| Arg | Type | Description |
|---|---|---|
task_id / project_id |
number | |
description |
string | |
start |
string | RFC3339 |
duration |
number | Seconds |
billable |
boolean | |
tag_ids |
number[] | |
time_block_id |
number | |
type |
"activity" | "break" |
focus_update_time_entry
Partial update. Requires time_entry_id. Optional task_id selects the task-scoped path.
focus_delete_time_entry
Deletes immediately. Requires time_entry_id. Optional task_id for the task-scoped path.
Clients
focus_list_clients
Optional name filter plus pagination.
focus_create_client
Requires name. Optional currency (ISO 4217).
Tags
focus_list_tags
Optional name, tag_id (array), pagination.
focus_create_tag
Requires name and color (hex or Focus color token).
Statuses & search
focus_list_statuses
List task statuses. Optional name, type, pagination.
focus_search
Unified search across time entries, tasks, and projects.
| Arg | Type | Required | Description |
|---|---|---|---|
keyword |
string | Yes | Search text |
per_group |
number | No | Results per group |
project_id / task_id |
number | No | Scope |
only_me / include_drafts |
boolean | No |
Behavior notes
- Mutations are immediate — create / update / delete / start / stop have no confirmation step.
- Project tags on create — some Focus plans/roles reject
tag_idsonPOST. The tool creates the project first, then PATCHes tags; on failure you still get the project plus awarning. - Workspace context — session cookie endpoints are not used; set org + workspace env vars.
- Quota — Focus enforces per-user-per-org hourly limits (e.g. Free ~30/hour). HTTP 402 means quota exhausted; wait for
X-Toggl-Quota-Resets-In. Prefer env IDs so tools do not rediscover context every call.
Development
git clone https://github.com/copperline-ai/toggl-focus-mcp.git
cd toggl-focus-mcp
npm install
npm run check # typecheck + unit/mocked MCP tests + build (CI gate)
npm run test:live # optional — real Focus API; local only, needs .env
node dist/index.js
npm run check is the same gate used by GitHub Actions on PRs and before publish. It uses mocked Focus responses — CI never calls your real Toggl account.
Live MCP tests (local only)
Optional suite against a real Focus workspace. Not run in CI.
- Copy
.env.example→.envand set your Focus key + org/workspace IDs - Run:
npm run test:live
Reuses stable fixtures (client Toggl Focus, project Toggl Focus MCP, task MCP live test, tag MCP live). Disposable time entries are deleted. Paces ~1 req/sec for rate limits. .env is gitignored and not published.
Publishing
Releases use release-it + AI Gateway (semver bump, changelog, GitHub Release, npm publish):
npm run release:dry-run
npm pack --dry-run
CI secrets: NPM_ACCESS_TOKEN, AI_GATEWAY_API_KEY.
Vendored OpenAPI: openapi/focus.json from Focus OpenAPI.
Related
- Focus docs: engineering.toggl.com/docs/focus
- Focus auth: Bearer API keys
- Official OAuth MCP:
@togglhq/mcp
License
MIT
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。