@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 +6 -0
- package/README.md +29 -281
- package/build/index.d.ts +2 -1034
- package/build/index.js +24 -17
- package/package.json +4 -7
- package/skills/toggl-mcp/INTERNAL.md +39 -0
- package/skills/toggl-mcp/SKILL.md +11 -6
package/build/index.js
CHANGED
|
@@ -32260,7 +32260,7 @@ async function fetchAccessibleWorkspaces(accountsApiUrl, token) {
|
|
|
32260
32260
|
}));
|
|
32261
32261
|
}
|
|
32262
32262
|
async function resolveAuthenticatedWorkspace(workspaces, options) {
|
|
32263
|
-
if (workspaces.length === 0) throw new Error("No
|
|
32263
|
+
if (workspaces.length === 0) throw new Error("No Toggl 2.0 workspaces found for this account.");
|
|
32264
32264
|
if (options.explicitWorkspaceId !== void 0) {
|
|
32265
32265
|
const match = workspaces.find((w) => w.workspace_id === options.explicitWorkspaceId);
|
|
32266
32266
|
if (!match) throw new Error(`Workspace ${options.explicitWorkspaceId} not found. Available: ${workspaces.map((w) => `${w.workspace_id} (${w.workspace_name})`).join(", ")}`);
|
|
@@ -32282,6 +32282,13 @@ async function resolveAuthenticatedWorkspace(workspaces, options) {
|
|
|
32282
32282
|
}
|
|
32283
32283
|
throw new WorkspaceSelectionRequiredError$1(workspaces);
|
|
32284
32284
|
}
|
|
32285
|
+
const PUBLIC_CLI_PACKAGE_NAME = "@togglhq/cli";
|
|
32286
|
+
const PUBLIC_MCP_PACKAGE_NAME = "@togglhq/mcp";
|
|
32287
|
+
`${PUBLIC_CLI_PACKAGE_NAME}`;
|
|
32288
|
+
`${PUBLIC_MCP_PACKAGE_NAME}`;
|
|
32289
|
+
function npxMcpAuthCommand() {
|
|
32290
|
+
return `npx ${PUBLIC_MCP_PACKAGE_NAME} auth`;
|
|
32291
|
+
}
|
|
32285
32292
|
async function refreshTokens(accountsApiUrl, refreshToken) {
|
|
32286
32293
|
const params = new URLSearchParams({
|
|
32287
32294
|
grant_type: "refresh_token",
|
|
@@ -32297,7 +32304,7 @@ async function refreshTokens(accountsApiUrl, refreshToken) {
|
|
|
32297
32304
|
}
|
|
32298
32305
|
async function getValidToken$1(scope = "cli", profile) {
|
|
32299
32306
|
const authConfig = loadProfile(scope, profile);
|
|
32300
|
-
if (!authConfig) throw new Error(scope === "cli" ? "Not authenticated. Run `toggl auth` to sign in." :
|
|
32307
|
+
if (!authConfig) throw new Error(scope === "cli" ? "Not authenticated. Run `toggl auth` to sign in." : `Not authenticated. Run \`${npxMcpAuthCommand()}\` to sign in.`);
|
|
32301
32308
|
const now = Date.now() / 1e3;
|
|
32302
32309
|
if (authConfig.expires_at > now + 60) return authConfig.access_token;
|
|
32303
32310
|
const tokens = await refreshTokens(authConfig.accounts_api_url, authConfig.refresh_token);
|
|
@@ -32313,11 +32320,11 @@ async function getValidToken$1(scope = "cli", profile) {
|
|
|
32313
32320
|
return authConfig.access_token;
|
|
32314
32321
|
}
|
|
32315
32322
|
function requireMcpDeveloperProfile(profile) {
|
|
32316
|
-
if (!loadProfile("mcp", profile)) throw new Error(
|
|
32323
|
+
if (!loadProfile("mcp", profile)) throw new Error(`Not authenticated. Call the auth tool or run \`${npxMcpAuthCommand()}\`.`);
|
|
32317
32324
|
const dev = loadDeveloperToolsConfig();
|
|
32318
|
-
if (!dev?.profiles) throw new Error(
|
|
32325
|
+
if (!dev?.profiles) throw new Error(`Not authenticated. Call the auth tool or run \`${npxMcpAuthCommand()}\`.`);
|
|
32319
32326
|
const profileKey = profile ?? dev.active.mcp;
|
|
32320
|
-
if (!profileKey || !dev.profiles[profileKey]) throw new Error(
|
|
32327
|
+
if (!profileKey || !dev.profiles[profileKey]) throw new Error(`Not authenticated. Call the auth tool or run \`${npxMcpAuthCommand()}\`.`);
|
|
32321
32328
|
return {
|
|
32322
32329
|
profileKey,
|
|
32323
32330
|
auth: dev.profiles[profileKey]
|
|
@@ -32392,7 +32399,7 @@ async function runAuthFlow(accountsApiUrl = "https://accounts.toggl.com", focusA
|
|
|
32392
32399
|
focusApiUrl = pendingContext.focus_api_url;
|
|
32393
32400
|
log("Continuing MCP authentication with existing session...\n");
|
|
32394
32401
|
} else {
|
|
32395
|
-
log("Toggl
|
|
32402
|
+
log("Toggl 2.0 MCP — Authentication\n");
|
|
32396
32403
|
const { code, verifier, redirectUri } = await obtainTogglOAuthAuthorizationCode({
|
|
32397
32404
|
accountsApiUrl,
|
|
32398
32405
|
flowMode: options.oauthFlowMode ?? (options.manualPrompt ? "manual" : "local"),
|
|
@@ -32459,7 +32466,7 @@ async function runAuthFlow(accountsApiUrl = "https://accounts.toggl.com", focusA
|
|
|
32459
32466
|
const AUTH_ERROR = {
|
|
32460
32467
|
ok: false,
|
|
32461
32468
|
status: 401,
|
|
32462
|
-
message:
|
|
32469
|
+
message: `Not authenticated. Call the auth tool first (or run \`${npxMcpAuthCommand()}\` manually).`
|
|
32463
32470
|
};
|
|
32464
32471
|
const FOCUS_CLIENT_SYNC_PASSTHROUGH_PROP_KEYS = [
|
|
32465
32472
|
"httpClient",
|
|
@@ -44027,7 +44034,7 @@ const schedulerOverrides = {
|
|
|
44027
44034
|
"focus.scheduler.validate-instructions": { hidden: true }
|
|
44028
44035
|
};
|
|
44029
44036
|
const searchOverrides = { "focus.search.search": {
|
|
44030
|
-
description: "Search across
|
|
44037
|
+
description: "Search across Toggl 2.0 entities.",
|
|
44031
44038
|
cli: {
|
|
44032
44039
|
group: [],
|
|
44033
44040
|
command: "search",
|
|
@@ -44813,11 +44820,11 @@ Entity mutations and \`profile-remove\` issue a \`confirm_token\` on the first c
|
|
|
44813
44820
|
- Task priority levels when setting priority: \`none\`, \`low\`, \`medium\`, \`high\`.
|
|
44814
44821
|
- Time blocks are planned calendar time; time entries are tracked time.
|
|
44815
44822
|
`;
|
|
44816
|
-
if (options.authenticated) return `You are connected to the Toggl
|
|
44823
|
+
if (options.authenticated) return `You are connected to the Toggl 2.0 workspace ${options.workspaceLabel ?? "your workspace"}.
|
|
44817
44824
|
|
|
44818
44825
|
${core}`;
|
|
44819
|
-
return `Toggl
|
|
44820
|
-
Call the auth tool to authenticate (or run
|
|
44826
|
+
return `Toggl 2.0 MCP is not authenticated.
|
|
44827
|
+
Call the auth tool to authenticate (or run ${npxMcpAuthCommand()} manually).
|
|
44821
44828
|
|
|
44822
44829
|
${core}`;
|
|
44823
44830
|
}
|
|
@@ -45641,7 +45648,7 @@ function registerWorkspaceTools(server) {
|
|
|
45641
45648
|
if (!config) return {
|
|
45642
45649
|
content: [{
|
|
45643
45650
|
type: "text",
|
|
45644
|
-
text:
|
|
45651
|
+
text: `Not authenticated. Call auth (or run \`${npxMcpAuthCommand()}\`).`
|
|
45645
45652
|
}],
|
|
45646
45653
|
isError: true
|
|
45647
45654
|
};
|
|
@@ -45677,7 +45684,7 @@ function registerWorkspaceTools(server) {
|
|
|
45677
45684
|
if (!config) return {
|
|
45678
45685
|
content: [{
|
|
45679
45686
|
type: "text",
|
|
45680
|
-
text:
|
|
45687
|
+
text: `Not authenticated. Call auth (or run \`${npxMcpAuthCommand()}\`).`
|
|
45681
45688
|
}],
|
|
45682
45689
|
isError: true
|
|
45683
45690
|
};
|
|
@@ -45791,7 +45798,7 @@ function registerWorkspaceTools(server) {
|
|
|
45791
45798
|
});
|
|
45792
45799
|
server.registerTool("auth", {
|
|
45793
45800
|
title: "Authenticate MCP",
|
|
45794
|
-
description: "Authenticate this MCP server with Toggl
|
|
45801
|
+
description: "Authenticate this MCP server with Toggl 2.0 via OAuth. Opens browser login and stores credentials locally. Optionally pass workspace_id to pick a specific workspace when multiple are available.",
|
|
45795
45802
|
annotations: {
|
|
45796
45803
|
readOnlyHint: false,
|
|
45797
45804
|
destructiveHint: false,
|
|
@@ -45946,7 +45953,7 @@ import_main.default.config({
|
|
|
45946
45953
|
quiet: true,
|
|
45947
45954
|
ignore: ["MISSING_ENV_FILE"]
|
|
45948
45955
|
});
|
|
45949
|
-
const packageVersion = "1.5.
|
|
45956
|
+
const packageVersion = "1.5.21";
|
|
45950
45957
|
function resolvePublicUrls() {
|
|
45951
45958
|
return {
|
|
45952
45959
|
focusApiUrl: process.env.TOGGL_FOCUS_API_URL ?? "https://focus.toggl.com",
|
|
@@ -45983,7 +45990,7 @@ function bootstrapServer(options = {}) {
|
|
|
45983
45990
|
applyResolvedUrls(urls);
|
|
45984
45991
|
const config = loadConfig();
|
|
45985
45992
|
const authenticated = Boolean(config);
|
|
45986
|
-
console.error(`Using
|
|
45993
|
+
console.error(`Using Toggl 2.0 API: ${urls.focusApiUrl}`);
|
|
45987
45994
|
const client = createAuthenticatedClientProxy();
|
|
45988
45995
|
const workspaceLabel = config ? `${config.workspace_name ?? "Workspace"} (ID: ${config.workspace_id})` : void 0;
|
|
45989
45996
|
const rawServer = new McpServer({
|
|
@@ -46000,7 +46007,7 @@ function bootstrapServer(options = {}) {
|
|
|
46000
46007
|
const transport = new StdioServerTransport();
|
|
46001
46008
|
options.beforeConnect?.();
|
|
46002
46009
|
await server.connect(transport);
|
|
46003
|
-
console.error(config ? `Toggl
|
|
46010
|
+
console.error(config ? `Toggl 2.0 MCP server running on stdio (workspace: ${workspaceLabel})` : "Toggl 2.0 MCP server running on stdio (not authenticated)");
|
|
46004
46011
|
}
|
|
46005
46012
|
main().catch((err) => {
|
|
46006
46013
|
console.error("Fatal error:", err);
|
package/package.json
CHANGED
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@togglhq/mcp",
|
|
3
|
-
"version": "1.5.
|
|
4
|
-
"description": "Toggl
|
|
3
|
+
"version": "1.5.21",
|
|
4
|
+
"description": "Toggl 2.0 MCP server for Claude Code, Claude Desktop, and other MCP clients.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
|
-
"repository": {
|
|
7
|
-
"type": "git",
|
|
8
|
-
"url": "https://github.com/toggl/toggl-mcp.git"
|
|
9
|
-
},
|
|
10
6
|
"type": "module",
|
|
11
7
|
"publishConfig": {
|
|
12
8
|
"registry": "https://registry.npmjs.org",
|
|
@@ -16,7 +12,8 @@
|
|
|
16
12
|
"build/**/*.js",
|
|
17
13
|
"build/**/*.d.ts",
|
|
18
14
|
"skills/**",
|
|
19
|
-
"README.md"
|
|
15
|
+
"README.md",
|
|
16
|
+
"LICENSE"
|
|
20
17
|
],
|
|
21
18
|
"bin": {
|
|
22
19
|
"mcp": "./build/index.js",
|
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
Install `@toggl/mcp-internal` from **GitHub Packages** for internal builds that include staging, MS environments, and telemetry (`toggl-mcp-internal` / `mcp-internal` bins).
|
|
4
4
|
|
|
5
|
+
Configure `~/.npmrc` with a GitHub Packages token (`read:packages`) and Toggl org access:
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
@toggl:registry=https://npm.pkg.github.com/
|
|
9
|
+
//npm.pkg.github.com/:_authToken=<GH_NPM_TOKEN>
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install @toggl/mcp-internal
|
|
14
|
+
# or: pnpm add @toggl/mcp-internal
|
|
15
|
+
```
|
|
16
|
+
|
|
5
17
|
## Environments
|
|
6
18
|
|
|
7
19
|
Use the public npm build by default. Use the GitHub internal build only when a Toggl engineer asks for staging or a named MS environment.
|
|
@@ -35,3 +47,30 @@ SENTRY_DSN=off toggl-mcp-internal
|
|
|
35
47
|
```
|
|
36
48
|
|
|
37
49
|
Burst detection is enabled when telemetry is enabled. It attaches retry metadata to Sentry spans and logs warnings when an MCP client repeats the same tool rapidly.
|
|
50
|
+
|
|
51
|
+
## Maintainer: from source
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
git clone <private-repo-url>
|
|
55
|
+
cd toggl-mcp
|
|
56
|
+
pnpm install
|
|
57
|
+
pnpm run build
|
|
58
|
+
node packages/mcp/build/index.js auth
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Maintainer: GitHub Release `.mcpb` bundles
|
|
62
|
+
|
|
63
|
+
Internal releases attach per-platform binary bundles (no Node on `PATH`):
|
|
64
|
+
|
|
65
|
+
- `toggl-focus-mcp-<version>-darwin-arm64.mcpb` (+ `.sha256`)
|
|
66
|
+
- `toggl-focus-mcp-<version>-darwin-x64.mcpb` (+ `.sha256`)
|
|
67
|
+
- `toggl-focus-mcp-<version>-linux-x64.mcpb` (+ `.sha256`)
|
|
68
|
+
- `toggl-focus-mcp-<version>-win32-x64.mcpb` (+ `.sha256`)
|
|
69
|
+
|
|
70
|
+
Download from the `@togglhq/mcp@<version>` GitHub release tag and open in a compatible MCP client.
|
|
71
|
+
|
|
72
|
+
Node-based MCPB for debugging: `pnpm --filter @toggl/mcp run build:mcpb:node`.
|
|
73
|
+
|
|
74
|
+
## Maintainer: publishing
|
|
75
|
+
|
|
76
|
+
Public npm: `@togglhq/mcp` via Trusted Publishing. Internal: `@toggl/mcp-internal` on GitHub Packages. See repo `docs/public-publishing.md` and `AGENTS.md`.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: toggl-mcp
|
|
3
|
-
description: Use the Toggl
|
|
3
|
+
description: Use the Toggl 2.0 MCP server to read and mutate Toggl 2.0 data (tasks, projects, time blocks, time entries, saved views, custom fields, attachments, organization and org-* domains, org-time-off-me, shared-status/holidays/working-hours tools), manage workspaces and saved profiles, authenticate, and mirror CLI-style workflows from an MCP client. Trigger when the user connects through Model Context Protocol tools rather than the terminal, or asks how to use toggl-focus MCP tools, confirm_token, dry_run, file uploads/downloads, workspace refresh, or profile switching.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# Toggl
|
|
6
|
+
# Toggl 2.0 MCP
|
|
7
7
|
|
|
8
8
|
The MCP server exposes **entity tools** (one tool per domain, for example `tasks`, `projects`) plus **workspace**, **profile**, and **auth** tools. Behavior aligns with the shared `@toggl/operations` catalog used by `toggl` CLI—see the `toggl-cli` skill for terminal equivalents (`toggl --json`, `--dry-run`, etc.).
|
|
9
9
|
|
|
@@ -27,11 +27,16 @@ The MCP server exposes **entity tools** (one tool per domain, for example `tasks
|
|
|
27
27
|
- **Workspace/auth**: **workspace-list** (optional `refresh`), **workspace-switch**, **profile-list**, **profile-switch**, **profile-remove**, **auth**, **logout**.
|
|
28
28
|
- Catalog entries marked hidden (e.g. calendar integrations, scheduler helpers, utilization targets) are omitted—parity with `visibleOperations()` in the CLI.
|
|
29
29
|
|
|
30
|
-
##
|
|
30
|
+
## Install
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
```bash
|
|
33
|
+
npm install @togglhq/mcp
|
|
34
|
+
npx @togglhq/mcp auth
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Pair with the `toggl-cli` skill for terminal equivalents (`toggl --json`, `--dry-run`, etc.).
|
|
33
38
|
|
|
34
39
|
## Read next
|
|
35
40
|
|
|
36
|
-
-
|
|
37
|
-
-
|
|
41
|
+
- Bundled package README (in your `node_modules/@togglhq/mcp` install)
|
|
42
|
+
- `toggl-cli` skill for CLI parity
|