@togglhq/mcp 1.5.19
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/README.md +344 -0
- package/build/index.d.ts +9111 -0
- package/build/index.js +46015 -0
- package/package.json +63 -0
- package/skills/toggl-mcp/INTERNAL.md +37 -0
- package/skills/toggl-mcp/SKILL.md +37 -0
package/README.md
ADDED
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
# Toggl Focus MCP Server
|
|
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).
|
|
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)
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install @togglhq/mcp
|
|
13
|
+
# or: pnpm add @togglhq/mcp
|
|
14
|
+
```
|
|
15
|
+
|
|
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):
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npx @togglhq/mcp auth
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
For one-off runs without a local install: `npx -y @togglhq/mcp auth`.
|
|
37
|
+
|
|
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)
|
|
70
|
+
|
|
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
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
claude mcp add toggl-focus -- npx @toggl/mcp
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
#### Claude Desktop
|
|
82
|
+
|
|
83
|
+
Add to your Claude Desktop config file:
|
|
84
|
+
|
|
85
|
+
- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
86
|
+
- **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
|
|
87
|
+
|
|
88
|
+
```json
|
|
89
|
+
{
|
|
90
|
+
"mcpServers": {
|
|
91
|
+
"toggl-focus": {
|
|
92
|
+
"command": "node",
|
|
93
|
+
"args": ["/absolute/path/to/toggl-mcp/build/index.js"]
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
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.
|
|
100
|
+
|
|
101
|
+
## Authentication
|
|
102
|
+
|
|
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).
|
|
104
|
+
|
|
105
|
+
> **Upgrading from an older version?** Sessions previously stored at `~/.toggl-focus-mcp/config.json` are still read automatically — no re-authentication needed.
|
|
106
|
+
|
|
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
|
|
110
|
+
|
|
111
|
+
For CI or headless environments where browser-based OAuth is not available:
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
claude mcp add toggl-focus \
|
|
115
|
+
-s user \
|
|
116
|
+
-e TOGGL_WORKSPACE_ID=<your-workspace-id> \
|
|
117
|
+
-e TOGGL_API_TOKEN=<your-api-token> \
|
|
118
|
+
-e TOGGL_ORGANIZATION_ID=<your-org-id> \
|
|
119
|
+
-e TOGGL_USER_ID=<your-user-id> \
|
|
120
|
+
-- npx @toggl/mcp
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Tools
|
|
124
|
+
|
|
125
|
+
### Entity tools
|
|
126
|
+
|
|
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
|
+
```
|
|
328
|
+
|
|
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.
|
|
330
|
+
|
|
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`).
|
|
332
|
+
|
|
333
|
+
### Publishing
|
|
334
|
+
|
|
335
|
+
CI publishes `@toggl/mcp` to [GitHub Packages](https://github.com/features/packages) when pending Changesets are merged to `main`.
|
|
336
|
+
|
|
337
|
+
The same publish workflow also cross-compiles **binary** MCP bundles with Bun and attaches, per platform:
|
|
338
|
+
|
|
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`)
|
|
343
|
+
|
|
344
|
+
These assets are attached to the GitHub release tag `@toggl/mcp@<version>`.
|