@doist/todoist-mcp 13.11.1 → 14.0.0

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.
@@ -1,16 +1,15 @@
1
+ import { McpServerOptions } from '@doist/mcp-core/host';
1
2
  import { McpServer } from '@modelcontextprotocol/server';
2
3
  import { FEATURE_NAMES, Feature, FeatureName, Features } from './mcp-helpers.js';
3
4
  export declare const instructions = "\n## Todoist Task and Project Management Tools\n\nYou have access to comprehensive Todoist management tools for personal productivity and team collaboration. Use these tools to help users manage tasks, projects, sections, comments, and assignments effectively.\n\n### Core Capabilities:\n- Create, update, complete, and search tasks with rich metadata (priorities, due dates, durations, assignments)\n- Manage projects and sections with flexible organization\n- Handle comments and collaboration features\n- Bulk assignment operations for team workflows\n- Get overviews and insights about workload and progress\n\n### Choosing between tools\n\nWhat each tool does and how to fill its parameters is in the tool's own description and input schema. This section covers only what those cannot: which tool to reach for, and how tools relate to each other.\n\n**Dates**\n\n- To move a task to a different date or time use **reschedule-tasks**, never **update-tasks**. It also sets duration, for time-blocking. update-tasks replaces the whole due string, so it refuses a dueString on a recurring task unless replaceRecurrence is true.\n- Never send a task's existing projectId, sectionId or parentId back to **update-tasks** \u2014 those fields are treated as a move.\n- All dates respect the user's timezone.\n- Todoist apps only display task durations under 24 hours. A longer one (\"36h\") or a day-based one (\"3d\") is stored and reported faithfully, but the apps show the task as having no duration \u2014 only set one when the user explicitly asks for it.\n\n**Finding things**\n\n- For \"what did I complete?\", call **user-info** for the asker's user ID, then **find-activity** with objectType=\"task\", eventType=\"completed\", initiatorId, and dateFrom/dateTo. Without initiatorId the answer covers every collaborator. find-activity reports completion events, including each occurrence of a recurring task; **find-completed-tasks** lists completed tasks, which is not the same question.\n- To resolve a person's name or email to a user ID, or to answer \"who is X?\", use **find-project-collaborators** with just a searchTerm. It covers every shared project you can access plus yourself, so an empty result means they collaborate on none of them \u2014 not that they do not exist.\n- Before assigning work to someone, call **find-project-collaborators** again with the target projectId. Resolving an ID only proves they collaborate on *some* project you can see; assignment fails unless they collaborate on that one.\n- To find out whether a task hides subtasks, use **fetch-object** with includeChildren rather than a speculative **find-tasks** call.\n- Filter tasks by label **name**. Label IDs are only for **delete-object** and **update-labels**. Shared labels can be renamed but not recoloured, reordered or favourited.\n\n**Comments**\n\n- Comments notify only the people **add-comments** is handed. When a comment mentions someone, name them in `notifyUsers` \u2014 writing \"@Ana\" in the text notifies nobody. Omit `notifyUsers` to notify whoever the Todoist apps would, or pass `[\"none\"]` to stay silent.\n- Notification cannot be sent when editing a comment, only when adding one.\n\n**Deleting and archiving**\n\n- **delete-object** removes every object type; there is no per-type delete tool. Reminders use type \"reminder\", location reminders \"location_reminder\".\n- A workspace project must be archived with **project-management** before it can be deleted. A personal project can be deleted directly.\n\n**Templates**\n\n- Templates cannot be listed through this server, so only use an ID or URL the user gave you. To start a new project from one, call **add-projects** first and import into it. Imports write immediately and cannot be undone.\n\n**Project health**\n\n- Health data may be stale \u2014 check the isStale flag, and call **analyze-project-health** to refresh it before reading again.\n\n**Batches**\n\n- Prefer a batch tool over one call per item.\n- Where a batch tool returns per-item `failures` alongside successes, one failure does not undo the rest: never retry the whole batch, re-send only the items whose failure reason is fixable. **reschedule-tasks** is the exception \u2014 it has no per-item failures and throws if any task fails, so retry it as a whole.\n\nUse the **productivity-analysis** prompt for a combined productivity review \u2014 it pulls together user-info, get-productivity-stats and find-completed-tasks.\n\nAlways provide clear, actionable task titles and descriptions. Use the overview tools to give users context about their workload and project status.\n";
4
5
  /**
5
6
  * Create the MCP server.
6
- * @param todoistApiKey - The API key for the todoist account.
7
+ * @param token - The user's Todoist API token.
7
8
  * @param baseUrl - The base URL for the todoist API.
8
9
  * @param features - Features to enable for the server.
9
10
  * @returns the MCP server.
10
11
  */
11
- declare function getMcpServer({ todoistApiKey, baseUrl, features, }: {
12
- todoistApiKey: string;
13
- baseUrl?: string;
12
+ declare function getMcpServer({ token, baseUrl, features, }: McpServerOptions & {
14
13
  features?: Features;
15
14
  }): McpServer;
16
15
  export { FEATURE_NAMES, type Feature, type FeatureName, type Features, getMcpServer };
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAA;AAExD,OAAO,EACH,aAAa,EACb,KAAK,OAAO,EACZ,KAAK,WAAW,EAChB,KAAK,QAAQ,EAEhB,MAAM,kBAAkB,CAAA;AAMzB,eAAO,MAAM,YAAY,qhJAyDxB,CAAA;AAgBD;;;;;;GAMG;AAEH,iBAAS,YAAY,CAAC,EAClB,aAAa,EACb,OAAO,EACP,QAAa,GAChB,EAAE;IACC,aAAa,EAAE,MAAM,CAAA;IACrB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,QAAQ,CAAA;CACtB,aA+CA;AAED,OAAO,EAAE,aAAa,EAAE,KAAK,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,QAAQ,EAAE,YAAY,EAAE,CAAA"}
1
+ {"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAA;AAExD,OAAO,EACH,aAAa,EACb,KAAK,OAAO,EACZ,KAAK,WAAW,EAChB,KAAK,QAAQ,EAEhB,MAAM,kBAAkB,CAAA;AAMzB,eAAO,MAAM,YAAY,qhJAyDxB,CAAA;AAgBD;;;;;;GAMG;AAEH,iBAAS,YAAY,CAAC,EAClB,KAAK,EACL,OAAO,EACP,QAAa,GAChB,EAAE,gBAAgB,GAAG;IAClB,QAAQ,CAAC,EAAE,QAAQ,CAAA;CACtB,aA+CA;AAED,OAAO,EAAE,aAAa,EAAE,KAAK,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,QAAQ,EAAE,YAAY,EAAE,CAAA"}
@@ -27,7 +27,8 @@ type RequireValidTodoistTokenOptions = TokenSource & {
27
27
  * Express middleware that validates the Todoist API token before MCP processing.
28
28
  *
29
29
  * Returns HTTP 401 with a spec-compliant WWW-Authenticate header if the token
30
- * is invalid, allowing MCP clients to trigger OAuth token refresh.
30
+ * is invalid, allowing MCP clients to trigger OAuth token refresh, and 403 with
31
+ * an `insufficient_scope` challenge if it lacks a scope the tools need.
31
32
  */
32
33
  declare function requireValidTodoistToken(options: RequireValidTodoistTokenOptions): RequestHandler;
33
34
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"require-valid-todoist-token.d.ts","sourceRoot":"","sources":["../../src/middleware/require-valid-todoist-token.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAgB,OAAO,EAAE,cAAc,EAAY,MAAM,SAAS,CAAA;AAI9E,KAAK,iBAAiB,GAAG;IACrB,IAAI,EAAE,QAAQ,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,KAAK,kBAAkB,GAAG;IACtB,IAAI,EAAE,SAAS,CAAA;IACf,SAAS,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,MAAM,GAAG,SAAS,CAAA;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,KAAK,WAAW,GAAG,iBAAiB,GAAG,kBAAkB,CAAA;AAEzD,KAAK,+BAA+B,GAAG,WAAW,GAAG;IACjD;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IAEnB;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAA;CAC/B,CAAA;AA8DD;;;;;GAKG;AACH,iBAAS,wBAAwB,CAAC,OAAO,EAAE,+BAA+B,GAAG,cAAc,CAwC1F;AAED;;GAEG;AACH,iBAAS,yBAAyB,IAAI,IAAI,CAEzC;AAED,OAAO,EAAE,yBAAyB,EAAE,wBAAwB,EAAE,KAAK,+BAA+B,EAAE,CAAA"}
1
+ {"version":3,"file":"require-valid-todoist-token.d.ts","sourceRoot":"","sources":["../../src/middleware/require-valid-todoist-token.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAgB,OAAO,EAAE,cAAc,EAAY,MAAM,SAAS,CAAA;AAI9E,KAAK,iBAAiB,GAAG;IACrB,IAAI,EAAE,QAAQ,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,KAAK,kBAAkB,GAAG;IACtB,IAAI,EAAE,SAAS,CAAA;IACf,SAAS,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,MAAM,GAAG,SAAS,CAAA;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,KAAK,WAAW,GAAG,iBAAiB,GAAG,kBAAkB,CAAA;AAEzD,KAAK,+BAA+B,GAAG,WAAW,GAAG;IACjD;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IAEnB;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAA;CAC/B,CAAA;AAiGD;;;;;;GAMG;AACH,iBAAS,wBAAwB,CAAC,OAAO,EAAE,+BAA+B,GAAG,cAAc,CAiC1F;AAED;;GAEG;AACH,iBAAS,yBAAyB,IAAI,IAAI,CAEzC;AAED,OAAO,EAAE,yBAAyB,EAAE,wBAAwB,EAAE,KAAK,+BAA+B,EAAE,CAAA"}
@@ -0,0 +1,79 @@
1
+ import { validateBearerToken as _ } from "@doist/mcp-core/host";
2
+ import { $ as k, a0 as v } from "./mcp-server-DY_eceeG.js";
3
+ const w = "https://api.todoist.com", y = (e, t) => _({
4
+ // Resolved the way the SDK resolves its own requests against a custom base URL. An empty
5
+ // base (`TODOIST_BASE_URL=`) means the default, as it does for the SDK client.
6
+ url: new URL("/api/v1/user", t || w),
7
+ token: e,
8
+ headers: v({ label: "auth:validate-token" }),
9
+ fetch: k
10
+ }), g = 3e5, m = 12e4, f = 1e4, r = /* @__PURE__ */ new Map();
11
+ function E(e, t) {
12
+ return t ? `${e}::${t}` : e;
13
+ }
14
+ function C() {
15
+ const e = Date.now();
16
+ for (const [t, n] of r)
17
+ e >= n.expiresAt && r.delete(t);
18
+ }
19
+ function D(e) {
20
+ const t = r.get(e);
21
+ if (t && Date.now() < t.expiresAt)
22
+ return t.result;
23
+ t && r.delete(e);
24
+ }
25
+ function L(e, t, n) {
26
+ r.size >= f && C(), r.size >= f && r.clear(), r.set(e, { result: t, expiresAt: Date.now() + n });
27
+ }
28
+ function T(e, t) {
29
+ const n = [
30
+ ...t ? [`error="${t}"`] : [],
31
+ ...e ? [`resource_metadata="${e}"`] : []
32
+ ];
33
+ return n.length > 0 ? `Bearer ${n.join(", ")}` : "Bearer";
34
+ }
35
+ function h(e, t) {
36
+ e.status(401).set("WWW-Authenticate", T(t)).json({
37
+ error: "invalid_token",
38
+ error_description: "Todoist API token is invalid or expired"
39
+ });
40
+ }
41
+ function U(e, t) {
42
+ e.status(403).set(
43
+ "WWW-Authenticate",
44
+ T(t, "insufficient_scope")
45
+ ).json({
46
+ error: "insufficient_scope",
47
+ error_description: "Todoist API token does not have the required scopes"
48
+ });
49
+ }
50
+ function l(e, t, n, i) {
51
+ e === "valid" ? n() : e === "forbidden" ? U(t, i) : h(t, i);
52
+ }
53
+ function M(e) {
54
+ const t = e.type === "static" ? g : m, n = e.cacheTtlMs ?? t, { resourceMetadataUrl: i } = e;
55
+ return async (p, o, s) => {
56
+ const a = e.type === "static" ? e.apiKey : e.getApiKey(p);
57
+ if (!a) {
58
+ h(o, i);
59
+ return;
60
+ }
61
+ const d = E(a, e.baseUrl), u = D(d);
62
+ if (u !== void 0) {
63
+ l(u, o, s, i);
64
+ return;
65
+ }
66
+ let c;
67
+ try {
68
+ c = await y(a, e.baseUrl);
69
+ } catch (A) {
70
+ console.warn("[Token validation] Transient error, proceeding:", A), s();
71
+ return;
72
+ }
73
+ L(d, c, n), l(c, o, s, i);
74
+ };
75
+ }
76
+ export {
77
+ M as r,
78
+ y as v
79
+ };
@@ -22,6 +22,11 @@ export declare function buildUsageTrackingHeaders({ label, platform, sessionId,
22
22
  export declare function resetDefaultDispatcherForTests(): Promise<void>;
23
23
  export declare function setDispatcherModuleLoaderForTests(loader: () => Promise<DispatcherModule>): void;
24
24
  export declare function resetDispatcherModuleLoaderForTests(): void;
25
+ /**
26
+ * Sends a request the way the SDK sends its own: through its default dispatcher, which honours
27
+ * `HTTP_PROXY`, `HTTPS_PROXY` and `NO_PROXY`, with the `fetch` paired to it.
28
+ */
29
+ export declare function fetchThroughSdkTransport(url: string | URL, init: RequestInit): Promise<Response>;
25
30
  export declare function createTrackedFetch(baseFetch?: typeof fetch, tracking?: UsageTrackingConfig): CustomFetch;
26
31
  export declare function createTodoistClient(apiKey: string, { baseUrl, tracking, }?: {
27
32
  baseUrl?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"usage-tracking.d.ts","sourceRoot":"","sources":["../src/usage-tracking.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,WAAW,EAA4B,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAK3F,QAAA,MAAM,mBAAmB,QAAsB,CAAA;AAI/C,KAAK,mBAAmB,GAAG;IACvB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,KAAK,gBAAgB,GAAG;IACpB,UAAU,EAAE,OAAO,CAAA;IACnB,KAAK,CAAC,EAAE,OAAO,KAAK,CAAA;CACvB,CAAA;AAED,KAAK,gBAAgB,GAAG;IACpB,mBAAmB,EAAE,MAAM,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAAA;CACnE,CAAA;AAcD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,wBAAgB,2BAA2B,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAE5E;AAED,wBAAgB,yBAAyB,CAAC,EACtC,KAAK,EACL,QAAgB,EAChB,SAAwB,GAC3B,GAAE;IACC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;CAChB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAW9B;AAkGD,wBAAsB,8BAA8B,IAAI,OAAO,CAAC,IAAI,CAAC,CAcpE;AAED,wBAAgB,iCAAiC,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAE/F;AAED,wBAAgB,mCAAmC,IAAI,IAAI,CAE1D;AAmCD,wBAAgB,kBAAkB,CAC9B,SAAS,GAAE,OAAO,KAAwB,EAC1C,QAAQ,GAAE,mBAAwB,GACnC,WAAW,CA+Bb;AAED,wBAAgB,mBAAmB,CAC/B,MAAM,EAAE,MAAM,EACd,EACI,OAAO,EACP,QAAQ,GACX,GAAE;IACC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,mBAAmB,CAAA;CAC5B,GACP,UAAU,CAUZ;AAED,OAAO,EAAE,mBAAmB,EAAE,CAAA"}
1
+ {"version":3,"file":"usage-tracking.d.ts","sourceRoot":"","sources":["../src/usage-tracking.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,WAAW,EAA4B,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAK3F,QAAA,MAAM,mBAAmB,QAAsB,CAAA;AAI/C,KAAK,mBAAmB,GAAG;IACvB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,KAAK,gBAAgB,GAAG;IACpB,UAAU,EAAE,OAAO,CAAA;IACnB,KAAK,CAAC,EAAE,OAAO,KAAK,CAAA;CACvB,CAAA;AAED,KAAK,gBAAgB,GAAG;IACpB,mBAAmB,EAAE,MAAM,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAAA;CACnE,CAAA;AAcD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,wBAAgB,2BAA2B,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAE5E;AAED,wBAAgB,yBAAyB,CAAC,EACtC,KAAK,EACL,QAAgB,EAChB,SAAwB,GAC3B,GAAE;IACC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;CAChB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAW9B;AAkGD,wBAAsB,8BAA8B,IAAI,OAAO,CAAC,IAAI,CAAC,CAcpE;AAED,wBAAgB,iCAAiC,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAE/F;AAED,wBAAgB,mCAAmC,IAAI,IAAI,CAE1D;AAuBD;;;GAGG;AACH,wBAAsB,wBAAwB,CAC1C,GAAG,EAAE,MAAM,GAAG,GAAG,EACjB,IAAI,EAAE,WAAW,GAClB,OAAO,CAAC,QAAQ,CAAC,CAInB;AAcD,wBAAgB,kBAAkB,CAC9B,SAAS,GAAE,OAAO,KAAwB,EAC1C,QAAQ,GAAE,mBAAwB,GACnC,WAAW,CA+Bb;AAED,wBAAgB,mBAAmB,CAC/B,MAAM,EAAE,MAAM,EACd,EACI,OAAO,EACP,QAAQ,GACX,GAAE;IACC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,mBAAmB,CAAA;CAC5B,GACP,UAAU,CAUZ;AAED,OAAO,EAAE,mBAAmB,EAAE,CAAA"}
@@ -1,9 +1,17 @@
1
+ import { ValidateToken } from '@doist/mcp-core/host';
1
2
  /**
2
- * Validates a Todoist API token by making a lightweight API call.
3
+ * Validates a Todoist API token with a status-only call to the user endpoint.
3
4
  *
4
- * @returns `true` if the token is valid, `false` if it's an auth error (401/403).
5
- * @throws On transient errors (network failures, 5xx) so the caller can decide.
5
+ * Resolves `'valid'`, `'invalid'` (401) or `'forbidden'` (403), so a host can answer a token that
6
+ * lacks a scope with an RFC 6750 `insufficient_scope` challenge rather than a blanket 401. The
7
+ * body is never parsed, so a change to the user object can't turn a valid token into an error.
8
+ *
9
+ * The request goes out through the SDK's transport, so it honours the same proxy settings as
10
+ * every tool call, and carries the usage-tracking headers as `auth:validate-token`.
11
+ *
12
+ * @throws {TokenValidationError} (from `@doist/mcp-core/host`) for any other status, such as a
13
+ * 5xx, carrying it as `httpStatusCode`. Network and timeout errors propagate unchanged.
6
14
  */
7
- declare function validateTodoistToken(apiKey: string, baseUrl?: string): Promise<boolean>;
15
+ declare const validateTodoistToken: ValidateToken;
8
16
  export { validateTodoistToken };
9
17
  //# sourceMappingURL=validate-todoist-token.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"validate-todoist-token.d.ts","sourceRoot":"","sources":["../../src/utils/validate-todoist-token.ts"],"names":[],"mappings":"AAuBA;;;;;GAKG;AACH,iBAAe,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAYtF;AAED,OAAO,EAAE,oBAAoB,EAAE,CAAA"}
1
+ {"version":3,"file":"validate-todoist-token.d.ts","sourceRoot":"","sources":["../../src/utils/validate-todoist-token.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAuB,MAAM,sBAAsB,CAAA;AAO9E;;;;;;;;;;;;GAYG;AACH,QAAA,MAAM,oBAAoB,EAAE,aAQtB,CAAA;AAEN,OAAO,EAAE,oBAAoB,EAAE,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@doist/todoist-mcp",
3
- "version": "13.11.1",
3
+ "version": "14.0.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -67,7 +67,7 @@
67
67
  "prepare": "lefthook install --reset-hooks-path"
68
68
  },
69
69
  "dependencies": {
70
- "@doist/mcp-core": "0.1.1",
70
+ "@doist/mcp-core": "0.3.0",
71
71
  "@doist/todoist-sdk": "16.0.0",
72
72
  "@modelcontextprotocol/ext-apps": "2.0.4",
73
73
  "date-fns": "4.1.0",
@@ -1,72 +0,0 @@
1
- import { $ as A, a0 as v, a1 as T } from "./mcp-server-BhPX7dvL.js";
2
- const y = /* @__PURE__ */ new Set([401, 403]);
3
- function C(e) {
4
- const t = T(e);
5
- if (t !== void 0)
6
- return t;
7
- if (e !== null && typeof e == "object" && "response" in e)
8
- return T(e.response);
9
- }
10
- async function _(e, t) {
11
- const r = A(e, { baseUrl: t });
12
- try {
13
- return await v("auth:validate-token", () => r.getUser()), !0;
14
- } catch (a) {
15
- const i = C(a);
16
- if (i !== void 0 && y.has(i))
17
- return !1;
18
- throw a;
19
- }
20
- }
21
- const p = 3e5, w = 12e4, h = 1e4, n = /* @__PURE__ */ new Map();
22
- function k(e, t) {
23
- return t ? `${e}::${t}` : e;
24
- }
25
- function E() {
26
- const e = Date.now();
27
- for (const [t, r] of n)
28
- e >= r.expiresAt && n.delete(t);
29
- }
30
- function S(e) {
31
- const t = n.get(e);
32
- if (t && Date.now() < t.expiresAt)
33
- return t.valid;
34
- t && n.delete(e);
35
- }
36
- function g(e, t, r) {
37
- n.size >= h && E(), n.size >= h && n.clear(), n.set(e, { valid: t, expiresAt: Date.now() + r });
38
- }
39
- function x(e) {
40
- return e ? `Bearer resource_metadata="${e}"` : "Bearer";
41
- }
42
- function d(e, t) {
43
- e.status(401).set("WWW-Authenticate", x(t)).json({
44
- error: "invalid_token",
45
- error_description: "Todoist API token is invalid or expired"
46
- });
47
- }
48
- function M(e) {
49
- const t = e.type === "static" ? p : w, r = e.cacheTtlMs ?? t, { resourceMetadataUrl: a } = e;
50
- return async (i, s, c) => {
51
- const u = e.type === "static" ? e.apiKey : e.getApiKey(i);
52
- if (!u) {
53
- d(s, a);
54
- return;
55
- }
56
- const f = k(u, e.baseUrl), l = S(f);
57
- if (l !== void 0) {
58
- l ? c() : d(s, a);
59
- return;
60
- }
61
- try {
62
- const o = await _(u, e.baseUrl);
63
- g(f, o, r), o ? c() : d(s, a);
64
- } catch (o) {
65
- console.warn("[Token validation] Transient error, proceeding:", o), c();
66
- }
67
- };
68
- }
69
- export {
70
- M as r,
71
- _ as v
72
- };