@togglhq/mcp 1.5.19 → 1.5.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,6 @@
1
+ Copyright (c) Toggl. All rights reserved.
2
+
3
+ This software is proprietary to Toggl. Installation and use are permitted only
4
+ under applicable Toggl product terms, agreements, and policies.
5
+
6
+ See https://toggl.com/legal/ for current legal terms and policies.
package/README.md CHANGED
@@ -1,33 +1,15 @@
1
- # Toggl Focus MCP Server
1
+ # Toggl 2.0 MCP Server
2
2
 
3
- A local MCP (Model Context Protocol) server that connects to the Toggl Focus API. Works with any MCP client including Claude Code and Claude Desktop. Exposes generated entity-domain tools (`tasks`, `projects`, `time-blocks`, `time-entries`, and related domains), workspace/auth tools, and Focus query artifacts from [`packages/focus-queries`](../focus-queries).
3
+ A local MCP (Model Context Protocol) server that connects to the Toggl 2.0 API. Works with any MCP client including Claude Code and Claude Desktop.
4
4
 
5
- Published publicly as **`@togglhq/mcp`** on **npmjs.org**. Internal builds publish as **`@toggl/mcp-internal`** on GitHub Packages.
6
-
7
- Each GitHub release also includes **per-platform `.mcpb` bundles** (standalone executables; no Node.js on `PATH`) so users can install without registry access.
8
-
9
- ## Install from npm (public)
5
+ ## Install
10
6
 
11
7
  ```bash
12
8
  npm install @togglhq/mcp
13
9
  # or: pnpm add @togglhq/mcp
14
10
  ```
15
11
 
16
- No GitHub Packages token is required.
17
-
18
- ## Install from GitHub Packages (Toggl staff)
19
-
20
- Internal builds publish as **`@toggl/mcp-internal`**. You need a GitHub token with **`read:packages`** and access to the Toggl org, or installs can return 404.
21
-
22
- 1. Copy [`.npmrc.example`](.npmrc.example) into your project or `~/.npmrc` and replace `<GH_NPM_TOKEN>` with a PAT.
23
- 2. Install:
24
-
25
- ```bash
26
- npm install @toggl/mcp-internal
27
- # or: pnpm add @toggl/mcp-internal
28
- ```
29
-
30
- Run the CLI (after install):
12
+ Authenticate:
31
13
 
32
14
  ```bash
33
15
  npx @togglhq/mcp auth
@@ -35,50 +17,15 @@ npx @togglhq/mcp auth
35
17
 
36
18
  For one-off runs without a local install: `npx -y @togglhq/mcp auth`.
37
19
 
38
- ## Install from GitHub Release (`.mcpb`)
39
-
40
- If you do not have access to the private package registry, install from the release bundle instead:
41
-
42
- 1. Open the latest [GitHub release](https://github.com/toggl/toggl-mcp/releases).
43
- 2. Download the `.mcpb` for **your OS and CPU** (and the matching `.sha256` if you verify checksums):
44
- - **Apple Silicon macOS:** `toggl-focus-mcp-<version>-darwin-arm64.mcpb`
45
- - **Intel macOS:** `toggl-focus-mcp-<version>-darwin-x64.mcpb`
46
- - **Linux x64:** `toggl-focus-mcp-<version>-linux-x64.mcpb`
47
- - **Windows x64:** `toggl-focus-mcp-<version>-win32-x64.mcpb`
48
-
49
- 3. Open the `.mcpb` file in a compatible MCP client (for example, Claude Desktop) to install.
50
-
51
- These bundles embed a compiled server and **do not require Node.js** or `@toggl/mcp` registry access.
52
-
53
- For development or debugging you can still package a **Node-based** MCPB (requires end users to have Node 20+): `pnpm run build:mcpb:node` from this package (outputs `toggl-focus-mcp-<version>.mcpb`).
54
-
55
- ## Setup (from source)
56
-
57
- ```bash
58
- git clone https://github.com/toggl/toggl-mcp.git
59
- cd toggl-mcp
60
- pnpm install
61
- pnpm run build
62
- node build/index.js auth
63
- ```
64
-
65
- This will:
66
-
67
- 1. Open your browser to sign in with your Toggl account
68
- 2. Automatically discover your workspaces
69
- 3. Let you select your workspace (if you have multiple)
20
+ ## Add to your MCP client
70
21
 
71
- Authentication uses OAuth2 with PKCE — no API keys or passwords are entered in the terminal. Access tokens refresh automatically (1-hour access token, 4-week refresh token).
72
-
73
- ### Add to your MCP client
74
-
75
- #### Claude Code
22
+ ### Claude Code
76
23
 
77
24
  ```bash
78
- claude mcp add toggl-focus -- npx @toggl/mcp
25
+ claude mcp add toggl-focus -- npx @togglhq/mcp
79
26
  ```
80
27
 
81
- #### Claude Desktop
28
+ ### Claude Desktop
82
29
 
83
30
  Add to your Claude Desktop config file:
84
31
 
@@ -89,26 +36,24 @@ Add to your Claude Desktop config file:
89
36
  {
90
37
  "mcpServers": {
91
38
  "toggl-focus": {
92
- "command": "node",
93
- "args": ["/absolute/path/to/toggl-mcp/build/index.js"]
39
+ "command": "npx",
40
+ "args": ["@togglhq/mcp"]
94
41
  }
95
42
  }
96
43
  }
97
44
  ```
98
45
 
99
- Replace `/absolute/path/to/toggl-mcp` with the actual path to your clone, or use `npx` with `command`/`args` pointing at `@toggl/mcp` if installed from GitHub Packages (with `.npmrc` configured). Restart Claude Desktop to pick up the change.
46
+ Restart Claude Desktop after saving.
100
47
 
101
48
  ## Authentication
102
49
 
103
- Uses **OAuth2 with PKCE** via the Toggl Accounts service. Credentials are stored in `~/.toggl/focus-tools.json` (mode 0600). Access tokens refresh automatically — re-run `npx @toggl/mcp auth` only to switch workspaces or if your refresh token expires (after 4 weeks of inactivity).
50
+ Uses **OAuth2 with PKCE** via the Toggl Accounts service. Credentials are stored in `~/.toggl/focus-tools.json` (mode 0600). Access tokens refresh automatically — re-run `npx @togglhq/mcp auth` to switch workspaces or if your refresh token expires (after 4 weeks of inactivity).
104
51
 
105
52
  > **Upgrading from an older version?** Sessions previously stored at `~/.toggl-focus-mcp/config.json` are still read automatically — no re-authentication needed.
106
53
 
107
- > **Unified config vs legacy file:** MCP **logout** (and config cleanup helpers) only remove credentials when there is a matching profile row under **`~/.toggl/focus-tools.json`** with **`active.mcp`** set. If you authenticate solely via the legacy read shim and nothing was written to the unified file yet, logout may report that nothing was cleared—run **`npx @toggl/mcp auth`** once so tokens land in `focus-tools.json`, or remove the legacy file manually if you intend to discard that session.
108
-
109
- ### Alternative: Environment Variables
54
+ > **Unified config vs legacy file:** MCP **logout** only removes credentials when there is a matching profile row under **`~/.toggl/focus-tools.json`** with **`active.mcp`** set. Run **`npx @togglhq/mcp auth`** once to migrate into the unified file if logout reports nothing was cleared.
110
55
 
111
- For CI or headless environments where browser-based OAuth is not available:
56
+ ### CI or headless environments
112
57
 
113
58
  ```bash
114
59
  claude mcp add toggl-focus \
@@ -117,228 +62,31 @@ claude mcp add toggl-focus \
117
62
  -e TOGGL_API_TOKEN=<your-api-token> \
118
63
  -e TOGGL_ORGANIZATION_ID=<your-org-id> \
119
64
  -e TOGGL_USER_ID=<your-user-id> \
120
- -- npx @toggl/mcp
65
+ -- npx @togglhq/mcp
121
66
  ```
122
67
 
123
68
  ## Tools
124
69
 
125
70
  ### Entity tools
126
71
 
127
- MCP exposes **one tool per catalog entity domain** — the tool id equals `mcp.entityTool` from `@toggl/operations` (for example `tasks`, `projects`, `time-blocks`, `organization`, `org-invitations`, `shared-working-hours`). Each tool accepts:
128
-
129
- - **`action`** (required) — discriminator for the operation
130
- - **`data`** (optional) — payload for that action
131
- - **`confirm_token`** (optional) — second step for mutating operations (see below)
132
- - **`dry_run`** (optional) — when `true`, validates `data` and returns `{ dry_run, operation, input }` without calling the API (CLI `--dry-run` parity)
133
-
134
- CLI bulk mutations are nested (`toggl tasks bulk patch`, etc.); MCP uses hyphenated `action` values such as `bulk-patch` on the same entity tools.
135
-
136
- **Mutation confirmation:** mutating tools use a two-step flow. First call returns `confirm_required` with `confirm_token`; call the same tool again with `confirm_token` to execute once. `dry_run: true` skips execution and does not consume a token.
137
-
138
- ### Tool inventory (full action list)
139
-
140
- The server builds MCP **instructions** at startup from `@toggl/operations`, so clients always see the current domains and actions. CI checks durable inventory invariants in [`packages/mcp/src/__tests__/tool-inventory-invariants.test.ts`](src/__tests__/tool-inventory-invariants.test.ts) instead of snapshotting the full generated action list.
141
-
142
- ### Workspaces, profiles & auth
143
-
144
- - **workspace-list** — List cached workspaces; pass `{ "refresh": true }` to refetch from Accounts first (CLI `workspace list --refresh` parity)
145
- - **workspace-switch** — Switch the active workspace for MCP
146
- - **profile-list** — List rows in `~/.toggl/focus-tools.json` with MCP active flag (`active.mcp`)
147
- - **profile-switch** — Set `active.mcp` to an existing profile name (shared with CLI profiles)
148
- - **profile-remove** — Remove a profile row (shared storage; affects CLI too if it used that row). Same **`confirm_token`** two-step flow as entity mutations: first call returns `confirm_required`, second call passes `confirm_token` with the same `profile_name`.
149
- - **auth** — Authenticate the MCP server via OAuth
150
- - **logout** — Clear the current MCP active profile credentials
151
-
152
- Agent-oriented guidance: [`skills/toggl-mcp/SKILL.md`](skills/toggl-mcp/SKILL.md) (bundled in the npm package under `skills/`).
153
-
154
- ### Maintainers: regenerate Focus API coverage
155
-
156
- ```bash
157
- pnpm run generate:focus-queries
158
- pnpm run generate:focus-operations
159
- ```
160
-
161
- Set `GH_AUTH_TOKEN` in `packages/focus-queries/.env` before generation (see [`packages/focus-queries/README.md`](../focus-queries/README.md)). Querygen refreshes Focus request/type/schema artifacts first; the operations generator then exposes most generated endpoints to CLI/MCP by default, excluding internal, deprecated, unsafe, file-upload, and unsupported-signature endpoints blocklisted in `packages/operations/src/focus/blocklist.ts`.
162
-
163
- ## Architecture
164
-
165
- ```
166
- src/
167
- ├── index.ts # Entry point — CLI auth handler + MCP server bootstrap
168
- ├── instructions.ts # MCP server instructions + tool inventory from @toggl/operations
169
- ├── auth.ts # OAuth2 PKCE auth flow, token refresh, config file management
170
- ├── client.ts # Re-export of @toggl/cli-core FocusClient
171
- ├── authenticated-client.ts
172
- ├── utils.ts # Date helpers (@toggl/stdlib + cli-core), markdown tables, MCP response helpers
173
- ├── runtime/
174
- │ └── safety/ # Mutation confirmation gate
175
- └── tools/
176
- ├── generated-entity-tools.ts # Registers MCP entity tools from @toggl/operations
177
- ├── mcp-schema.ts
178
- ├── focus-tool-utils.ts
179
- ├── payload-helpers.ts
180
- └── workspace.ts # Workspace/auth tools
181
- packages/
182
- ├── cli-core/ # Auth/config/token primitives and FocusClient
183
- ├── operations/ # Shared operation catalog used by CLI and MCP
184
- └── focus-queries/ # Querygen mirror for Focus API types, schemas, and requests
185
- ```
186
-
187
- ### How it works
188
-
189
- The server runs as a **stdio MCP process**. Claude Code spawns it as a subprocess and communicates via JSON-RPC over stdin/stdout (stderr is used for logging).
190
-
191
- **Startup flow:**
192
-
193
- 1. `index.ts` checks for the `auth` CLI argument — if present, runs the auth flow and exits.
194
- 2. Otherwise, it loads credentials from `~/.toggl/focus-tools.json` when available (falls back to `~/.toggl-focus-mcp/config.json` for sessions created by older versions).
195
- 3. Creates an auth-aware `FocusClient` proxy that resolves credentials lazily per tool call.
196
- 4. Creates an `McpServer` and registers entity tools from `@toggl/operations`, plus workspace/auth tools.
197
- 5. Connects via `StdioServerTransport` and waits for tool calls.
198
-
199
- **Environment configuration:**
200
-
201
- The server reads an optional `.env` file from the project root and defaults to production (`focus.toggl.com`). You can override URLs directly via `TOGGL_FOCUS_API_URL` and `TOGGL_ACCOUNTS_API_URL` environment variables.
202
-
203
- ### Authentication details
204
-
205
- The auth flow (`auth.ts`) uses **OAuth2 Authorization Code with PKCE**:
206
-
207
- 1. Generates a PKCE code verifier and challenge (SHA-256, base64url).
208
- 2. Starts a local HTTP callback server on `localhost:8716`.
209
- 3. Opens the browser to `accounts.toggl.com/focus/login/` with OAuth parameters.
210
- 4. User logs in via the browser — the callback receives the authorization code.
211
- 5. Exchanges the code for access + refresh tokens via `POST /api/oauth/token`.
212
- 6. Fetches user info (`GET /api/me`) and workspaces (`GET /org/api/organizations/me`).
213
- 7. Saves tokens and workspace info to `~/.toggl/focus-tools.json` (mode 0600).
214
-
215
- **Token refresh** happens automatically: before each API request, the client checks the access token's expiry and refreshes it if it expires within 60 seconds. The refresh token is valid for 4 weeks.
216
-
217
- The stored config looks like:
218
-
219
- ```json
220
- {
221
- "access_token": "<OAuth access token>",
222
- "refresh_token": "<OAuth refresh token>",
223
- "expires_at": 1700000000,
224
- "user_id": 1234567,
225
- "organization_id": 12345,
226
- "workspace_id": 67890,
227
- "workspace_name": "My Workspace",
228
- "accounts_api_url": "https://accounts.toggl.com",
229
- "focus_api_url": "https://focus.toggl.com",
230
- "authenticated_at": "2025-01-15T10:00:00.000Z",
231
- "workspaces": [...]
232
- }
233
- ```
234
-
235
- ### HTTP client (`@toggl/cli-core/focus-client`)
236
-
237
- The MCP package re-exports `FocusClient` from `@toggl/cli-core`. That client uses generated request functions from `@toggl/focus-queries` and `@toggl/queries` where available, and handles:
238
-
239
- - **Auth**: Resolves a fresh token via the token provider before each request (handles OAuth2 refresh transparently).
240
- - **Required headers**: Includes `X-Toggl-PostHog-Data: {"platform_origin":"web"}` on all requests — the Focus API rejects write operations without this header.
241
- - **Generated request execution**: Calls generated request helpers for Focus, org, and shared-data endpoints instead of hand-building paths in the MCP package.
242
- - **Validation**: Validates outgoing mutation payloads with generated Valibot schemas and soft-validates responses for typed callers.
243
- - **Error handling**: Returns a discriminated union (`ApiResponse<T>`) — callers check `.ok` before accessing `.data`.
244
-
245
- ### Runtime design
246
-
247
- - **Entity tool handlers** are generated at startup from the shared `@toggl/operations` catalog.
248
- - **Input schemas** come from operation metadata; most payload schemas are generated Valibot schemas from query packages, with small hand-written wrappers for route IDs and curated list filters.
249
- - **Mutation gate** (`src/runtime/safety/mutation-gate.ts`) issues `confirm_token` values until the caller re-invokes the same mutating tool with that token.
250
-
251
- ### Key Focus API concepts
252
-
253
- | Concept | Description |
254
- | -------------- | -------------------------------------------------------------------------------------------------------------------------------- |
255
- | **Task** | Core work item. Has name, priority, status, project, assignees, dates, description, notes. |
256
- | **Project** | Groups tasks. Has name, color, dates, estimated time. |
257
- | **Time Block** | A scheduled calendar slot for a task (planned time). Has start time + duration in seconds. |
258
- | **Time Entry** | Actual tracked time. Created by start/stop tracking. Types: `activity` or `break`. |
259
- | **Status** | Workflow state (e.g. Todo, Doing, Done). Workspace-level, fetched from `/workspaces/{id}/statuses`. |
260
- | **User ID** | `user_account_id` from the workspace API response. Used as `assignee_user_id` in tasks and for the `toggl_user_id` query filter. |
261
-
262
- ### Maintenance model
263
-
264
- The intended maintenance direction is to keep MCP and CLI surfaces driven by generated API artifacts:
265
-
266
- 1. Regenerate `@toggl/focus-queries` when the Focus API changes.
267
- 2. Prefer generated request functions, generated Valibot payload schemas, and generated response schemas over hand-written HTTP/path/payload logic.
268
- 3. Keep `@toggl/operations` as the curated exposure layer for now: it defines which generated endpoints become public CLI/MCP operations, plus safety flags, command grouping, descriptions, and examples.
269
- 4. When exposing new endpoints, add operation metadata and `FocusClient` bindings only where the generated request layer cannot be consumed directly yet.
270
-
271
- Longer term, the main low-maintenance opportunity is generating the base operation catalog from querygen output and applying a small override map for visibility, safety, names, examples, and agent guidance.
272
-
273
- ## MCP Apps (inline UI)
274
-
275
- Cursor **2.6+**, Claude Desktop, and other MCP App hosts can render **view tools** inline in chat. The stdio server is unchanged; view tools are additive alongside entity tools (`tasks`, `projects`, …).
276
-
277
- - **Resource**: `ui://toggl-focus/app.html` (single React iframe bundled with `@toggl/design-system`)
278
- - **When to use**: Prefer view tools when the user asks to **show**, **see**, or **visualize** Focus data. Use entity tools for mutations, scripting, and non-UI hosts.
279
- - **Refresh**: The iframe re-calls the **same** view tool via `app.callServerTool` — there are no separate `*-refresh` tools.
280
-
281
- ### View tools
282
-
283
- | Tool | Use when |
284
- | ------------------------------ | ---------------------------- |
285
- | `focus-tasks-inbox` | Task list / backlog |
286
- | `focus-task-detail` | Single task deep-dive |
287
- | `focus-status-board` | Kanban-style status snapshot |
288
- | `focus-projects-overview` | Project list |
289
- | `focus-project-detail` | Single project overview |
290
- | `focus-milestones-roadmap` | Milestones by due date |
291
- | `focus-search-results` | Search across entities |
292
- | `focus-week-at-a-glance` | Week plan vs tracked time |
293
- | `focus-day-today` | Today's schedule |
294
- | `focus-time-log` | Time entries table |
295
- | `focus-time-blocks` | Scheduled blocks |
296
- | `focus-report-workload` | Team workload / utilization |
297
- | `focus-report-time-by-project` | Time grouped by project |
298
- | `focus-report-time-by-member` | Time grouped by member |
299
- | `focus-report-billable` | Billable summary |
300
- | `focus-report-task-throughput` | Task completion throughput |
301
- | `focus-team-roster` | Workspace members |
302
- | `focus-clients-directory` | Client list |
303
- | `focus-time-off-calendar` | Time off in range |
304
- | `focus-holidays-calendar` | Public holidays |
305
- | `focus-mutation-review` | Confirm pending mutation |
306
- | `focus-dry-run-preview` | Preview dry-run payload |
307
-
308
- Hosts without MCP App support still receive the same JSON tool results as entity tools.
309
-
310
- ### Adding a new entity action
311
-
312
- 1. Regenerate `@toggl/focus-queries` if the endpoint or schema is new.
313
- 2. Reuse the generated request function and Valibot schemas in `@toggl/cli-core` / `@toggl/operations`.
314
- 3. Add or update operation metadata in `packages/operations/src`.
315
- 4. Rebuild (`pnpm run build`) and update docs/skill guidance if the user-facing workflow changes.
316
-
317
- ### Development
318
-
319
- ```bash
320
- pnpm install # Install dependencies
321
- pnpm run build # Build MCP App iframe + compile TypeScript → build/
322
- pnpm run build:mcpb # Node-based .mcpb (same as build:mcpb:node)
323
- pnpm run build:mcpb:binary -- --target darwin-arm64 # Binary .mcpb (requires Bun); targets: darwin-arm64, darwin-x64, linux-x64, win32-x64
324
- pnpm run lint # Run Oxlint checks
325
- pnpm run lint:fix # Auto-fix lint issues when possible
326
- node build/index.js auth # (Re-)authenticate
327
- ```
72
+ One tool per domain (for example `tasks`, `projects`, `time-blocks`, `time-entries`, `organization`). Each tool accepts:
328
73
 
329
- Releases use [Changesets](https://github.com/changesets/changesets): run `pnpm run changeset` on a branch when you need a version bump, merge to `main`, and CI publishes to GitHub Packages when pending changesets exist.
74
+ - **`action`** (required)
75
+ - **`data`** (optional)
76
+ - **`confirm_token`** (optional) — second step for mutating operations
77
+ - **`dry_run`** (optional) — validates input without calling the API
330
78
 
331
- The project uses TypeScript with ES2022 target and Node16 module resolution. Output goes to `build/`. Package tests: `pnpm --filter @toggl/mcp test` (tool inventory invariants vs `@toggl/operations`).
79
+ **Mutation confirmation:** mutating tools return `confirm_required` with a `confirm_token` on the first call; repeat with `confirm_token` to execute.
332
80
 
333
- ### Publishing
81
+ ### Workspace, profiles, and auth
334
82
 
335
- CI publishes `@toggl/mcp` to [GitHub Packages](https://github.com/features/packages) when pending Changesets are merged to `main`.
83
+ - **workspace-list** list workspaces (`refresh: true` refetches from Accounts)
84
+ - **workspace-switch** — set the active workspace
85
+ - **profile-list**, **profile-switch**, **profile-remove** — manage `active.mcp` in `~/.toggl/focus-tools.json`
86
+ - **auth**, **logout** — sign in or clear the active MCP profile
336
87
 
337
- The same publish workflow also cross-compiles **binary** MCP bundles with Bun and attaches, per platform:
88
+ Agent-oriented guidance ships in `skills/toggl-mcp/SKILL.md` inside this package.
338
89
 
339
- - `toggl-focus-mcp-<version>-darwin-arm64.mcpb` (+ `.sha256`)
340
- - `toggl-focus-mcp-<version>-darwin-x64.mcpb` (+ `.sha256`)
341
- - `toggl-focus-mcp-<version>-linux-x64.mcpb` (+ `.sha256`)
342
- - `toggl-focus-mcp-<version>-win32-x64.mcpb` (+ `.sha256`)
90
+ ## License
343
91
 
344
- These assets are attached to the GitHub release tag `@toggl/mcp@<version>`.
92
+ Proprietary Toggl software. See [LICENSE](LICENSE) and [Toggl legal terms](https://toggl.com/legal/).