@todoist/comms-mcp 0.0.1 → 11.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.
- package/LICENSE +21 -0
- package/README.md +198 -34
- package/dist/comms-tool.d.ts +14 -0
- package/dist/comms-tool.js +1 -0
- package/dist/index.d.ts +1324 -0
- package/dist/index.js +55 -0
- package/dist/main.d.ts +2 -0
- package/dist/main.js +24 -0
- package/dist/mcp-helpers.d.ts +17 -0
- package/dist/mcp-helpers.js +40 -0
- package/dist/mcp-server.d.ts +10 -0
- package/dist/mcp-server.js +78 -0
- package/dist/tool-registry.d.ts +3 -0
- package/dist/tool-registry.js +49 -0
- package/dist/tools/build-link.d.ts +63 -0
- package/dist/tools/build-link.js +93 -0
- package/dist/tools/channel-output.d.ts +19 -0
- package/dist/tools/channel-output.js +47 -0
- package/dist/tools/create-channel.d.ts +55 -0
- package/dist/tools/create-channel.js +44 -0
- package/dist/tools/create-conversation.d.ts +49 -0
- package/dist/tools/create-conversation.js +75 -0
- package/dist/tools/create-thread.d.ts +67 -0
- package/dist/tools/create-thread.js +126 -0
- package/dist/tools/delete-object.d.ts +44 -0
- package/dist/tools/delete-object.js +84 -0
- package/dist/tools/fetch-inbox.d.ts +91 -0
- package/dist/tools/fetch-inbox.js +227 -0
- package/dist/tools/get-groups.d.ts +62 -0
- package/dist/tools/get-groups.js +116 -0
- package/dist/tools/get-mentions.d.ts +97 -0
- package/dist/tools/get-mentions.js +126 -0
- package/dist/tools/get-users.d.ts +58 -0
- package/dist/tools/get-users.js +107 -0
- package/dist/tools/get-workspaces.d.ts +61 -0
- package/dist/tools/get-workspaces.js +120 -0
- package/dist/tools/list-channels.d.ts +47 -0
- package/dist/tools/list-channels.js +89 -0
- package/dist/tools/list-conversations.d.ts +66 -0
- package/dist/tools/list-conversations.js +212 -0
- package/dist/tools/load-conversation.d.ts +92 -0
- package/dist/tools/load-conversation.js +128 -0
- package/dist/tools/load-thread.d.ts +127 -0
- package/dist/tools/load-thread.js +175 -0
- package/dist/tools/mark-done.d.ts +111 -0
- package/dist/tools/mark-done.js +275 -0
- package/dist/tools/mark-read.d.ts +73 -0
- package/dist/tools/mark-read.js +214 -0
- package/dist/tools/react.d.ts +59 -0
- package/dist/tools/react.js +97 -0
- package/dist/tools/reply.d.ts +69 -0
- package/dist/tools/reply.js +122 -0
- package/dist/tools/search-content.d.ts +103 -0
- package/dist/tools/search-content.js +138 -0
- package/dist/tools/update-channel.d.ts +53 -0
- package/dist/tools/update-channel.js +45 -0
- package/dist/tools/update-object.d.ts +52 -0
- package/dist/tools/update-object.js +161 -0
- package/dist/tools/update-user-info.d.ts +55 -0
- package/dist/tools/update-user-info.js +270 -0
- package/dist/tools/user-info.d.ts +32 -0
- package/dist/tools/user-info.js +16 -0
- package/dist/tools/user-output.d.ts +9 -0
- package/dist/tools/user-output.js +28 -0
- package/dist/usage-tracking.d.ts +23 -0
- package/dist/usage-tracking.js +41 -0
- package/dist/utils/attachments.d.ts +24 -0
- package/dist/utils/attachments.js +57 -0
- package/dist/utils/concurrency.d.ts +20 -0
- package/dist/utils/concurrency.js +24 -0
- package/dist/utils/constants.d.ts +5 -0
- package/dist/utils/constants.js +5 -0
- package/dist/utils/degrade.d.ts +81 -0
- package/dist/utils/degrade.js +149 -0
- package/dist/utils/output-schemas.d.ts +1283 -0
- package/dist/utils/output-schemas.js +657 -0
- package/dist/utils/read-position.d.ts +21 -0
- package/dist/utils/read-position.js +37 -0
- package/dist/utils/search-results.d.ts +36 -0
- package/dist/utils/search-results.js +82 -0
- package/dist/utils/target-types.d.ts +114 -0
- package/dist/utils/target-types.js +58 -0
- package/dist/utils/test-helpers.d.ts +95 -0
- package/dist/utils/test-helpers.js +231 -0
- package/dist/utils/tool-names.d.ts +25 -0
- package/dist/utils/tool-names.js +25 -0
- package/dist/utils/url-helpers.d.ts +3 -0
- package/dist/utils/url-helpers.js +10 -0
- package/dist/utils/user-status.d.ts +8 -0
- package/dist/utils/user-status.js +33 -0
- package/dist/utils/validate-comms-token.d.ts +13 -0
- package/dist/utils/validate-comms-token.js +22 -0
- package/package.json +85 -8
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export const ToolNames = {
|
|
2
|
+
USER_INFO: 'user-info',
|
|
3
|
+
UPDATE_USER_INFO: 'update-user-info',
|
|
4
|
+
FETCH_INBOX: 'fetch-inbox',
|
|
5
|
+
LOAD_THREAD: 'load-thread',
|
|
6
|
+
LOAD_CONVERSATION: 'load-conversation',
|
|
7
|
+
SEARCH_CONTENT: 'search-content',
|
|
8
|
+
GET_MENTIONS: 'get-mentions',
|
|
9
|
+
CREATE_CHANNEL: 'create-channel',
|
|
10
|
+
UPDATE_CHANNEL: 'update-channel',
|
|
11
|
+
CREATE_THREAD: 'create-thread',
|
|
12
|
+
CREATE_CONVERSATION: 'create-conversation',
|
|
13
|
+
UPDATE_OBJECT: 'update-object',
|
|
14
|
+
DELETE_OBJECT: 'delete-object',
|
|
15
|
+
REPLY: 'reply',
|
|
16
|
+
REACT: 'react',
|
|
17
|
+
MARK_DONE: 'mark-done',
|
|
18
|
+
MARK_READ: 'mark-read',
|
|
19
|
+
BUILD_LINK: 'build-link',
|
|
20
|
+
GET_WORKSPACES: 'get-workspaces',
|
|
21
|
+
GET_USERS: 'get-users',
|
|
22
|
+
GET_GROUPS: 'get-groups',
|
|
23
|
+
LIST_CHANNELS: 'list-channels',
|
|
24
|
+
LIST_CONVERSATIONS: 'list-conversations',
|
|
25
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { getFullCommsURL } from '@doist/comms-sdk';
|
|
2
|
+
export function getWorkspaceUrl(workspaceId) {
|
|
3
|
+
return getFullCommsURL({ workspaceId });
|
|
4
|
+
}
|
|
5
|
+
export function getChannelUrl(workspaceId, channelId) {
|
|
6
|
+
return getFullCommsURL({ workspaceId, channelId });
|
|
7
|
+
}
|
|
8
|
+
export function getConversationUrl(workspaceId, conversationId) {
|
|
9
|
+
return getFullCommsURL({ workspaceId, conversationId });
|
|
10
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { UserStatus } from '@doist/comms-sdk';
|
|
2
|
+
import type { UserInfoOutput } from './output-schemas.js';
|
|
3
|
+
type StatusOutput = NonNullable<UserInfoOutput['status']>;
|
|
4
|
+
declare function normaliseActiveUntil(activeUntil: string): string;
|
|
5
|
+
declare function toStatusOutput(status: UserStatus): StatusOutput;
|
|
6
|
+
/** The status lines of a user-info text, in the same `**Label:** value` form as the rest. */
|
|
7
|
+
declare function describeStatus(status: StatusOutput | undefined): string[];
|
|
8
|
+
export { describeStatus, normaliseActiveUntil, toStatusOutput };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Comms sends RFC 3339, but an end that fails to parse is still worth showing, so it is reported as
|
|
2
|
+
// sent. A set never gets this far with one: it fails the comparison with the end it asked for.
|
|
3
|
+
function normaliseActiveUntil(activeUntil) {
|
|
4
|
+
const parsed = new Date(activeUntil);
|
|
5
|
+
return Number.isNaN(parsed.getTime()) ? activeUntil : parsed.toISOString();
|
|
6
|
+
}
|
|
7
|
+
function toStatusOutput(status) {
|
|
8
|
+
const activeUntil = status.activeUntil ? normaliseActiveUntil(status.activeUntil) : undefined;
|
|
9
|
+
return {
|
|
10
|
+
message: status.message,
|
|
11
|
+
...(status.emoji ? { emoji: status.emoji } : {}),
|
|
12
|
+
...(activeUntil ? { activeUntil } : {}),
|
|
13
|
+
pauseNotifications: Boolean(status.effects?.pauseNotifications),
|
|
14
|
+
pauseActivity: Boolean(status.effects?.pauseActivity),
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/** The status lines of a user-info text, in the same `**Label:** value` form as the rest. */
|
|
18
|
+
function describeStatus(status) {
|
|
19
|
+
if (!status) {
|
|
20
|
+
return ['**Status:** none'];
|
|
21
|
+
}
|
|
22
|
+
const lines = [`**Status:** ${status.emoji ? `${status.emoji} ` : ''}${status.message}`];
|
|
23
|
+
lines.push(`**Status Until:** ${status.activeUntil ?? 'no end'}`);
|
|
24
|
+
const effects = [
|
|
25
|
+
status.pauseNotifications ? 'Comms notifications paused' : undefined,
|
|
26
|
+
status.pauseActivity ? 'Karma and streaks paused' : undefined,
|
|
27
|
+
].filter((effect) => effect !== undefined);
|
|
28
|
+
if (effects.length > 0) {
|
|
29
|
+
lines.push(`**Status Effects:** ${effects.join(', ')}`);
|
|
30
|
+
}
|
|
31
|
+
return lines;
|
|
32
|
+
}
|
|
33
|
+
export { describeStatus, normaliseActiveUntil, toStatusOutput };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type TokenValidationResult } from '@todoist/mcp-core/host';
|
|
2
|
+
/**
|
|
3
|
+
* Validates a Comms API token with a status-only call to the session-user endpoint.
|
|
4
|
+
*
|
|
5
|
+
* Resolves `'valid'`, `'invalid'` (401) or `'forbidden'` (403), so a host can answer a
|
|
6
|
+
* scope-deficient token with an RFC 6750 `insufficient_scope` challenge rather than a blanket
|
|
7
|
+
* 401. The request carries the usage-tracking headers, as the tool `auth:validate-token`.
|
|
8
|
+
*
|
|
9
|
+
* @throws {TokenValidationError} (from `@todoist/mcp-core/host`) for any other status, such as a
|
|
10
|
+
* 5xx or a 404 from a misconfigured base URL, carrying it as `httpStatusCode`. Network and
|
|
11
|
+
* timeout errors propagate unchanged.
|
|
12
|
+
*/
|
|
13
|
+
export declare function validateCommsToken(token: string, baseUrl?: string): Promise<TokenValidationResult>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { validateBearerToken } from '@todoist/mcp-core/host';
|
|
2
|
+
import { buildUsageTrackingHeaders } from '../usage-tracking.js';
|
|
3
|
+
/** Production Comms API base URL, used when no explicit base is given. */
|
|
4
|
+
const DEFAULT_BASE_URL = 'https://comms.todoist.com';
|
|
5
|
+
/**
|
|
6
|
+
* Validates a Comms API token with a status-only call to the session-user endpoint.
|
|
7
|
+
*
|
|
8
|
+
* Resolves `'valid'`, `'invalid'` (401) or `'forbidden'` (403), so a host can answer a
|
|
9
|
+
* scope-deficient token with an RFC 6750 `insufficient_scope` challenge rather than a blanket
|
|
10
|
+
* 401. The request carries the usage-tracking headers, as the tool `auth:validate-token`.
|
|
11
|
+
*
|
|
12
|
+
* @throws {TokenValidationError} (from `@todoist/mcp-core/host`) for any other status, such as a
|
|
13
|
+
* 5xx or a 404 from a misconfigured base URL, carrying it as `httpStatusCode`. Network and
|
|
14
|
+
* timeout errors propagate unchanged.
|
|
15
|
+
*/
|
|
16
|
+
export function validateCommsToken(token, baseUrl = DEFAULT_BASE_URL) {
|
|
17
|
+
return validateBearerToken({
|
|
18
|
+
url: `${baseUrl}/api/v1/users/get_session_user`,
|
|
19
|
+
token,
|
|
20
|
+
headers: buildUsageTrackingHeaders('auth:validate-token'),
|
|
21
|
+
});
|
|
22
|
+
}
|
package/package.json
CHANGED
|
@@ -1,10 +1,87 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
|
|
2
|
+
"name": "@todoist/comms-mcp",
|
|
3
|
+
"version": "11.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"types": "./dist/index.d.ts",
|
|
7
|
+
"mcpName": "com.doist/comms-mcp",
|
|
8
|
+
"bin": {
|
|
9
|
+
"comms-mcp": "dist/main.js"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"dist",
|
|
13
|
+
"package.json",
|
|
14
|
+
"LICENSE",
|
|
15
|
+
"README.md"
|
|
16
|
+
],
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"description": "MCP server and importable AI tools for the Doist Comms API",
|
|
19
|
+
"author": "Doist",
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/todoist/comms-mcp.git"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"comms",
|
|
26
|
+
"doist",
|
|
27
|
+
"ai",
|
|
28
|
+
"mcp",
|
|
29
|
+
"collaboration",
|
|
30
|
+
"model-context-protocol"
|
|
31
|
+
],
|
|
32
|
+
"publishConfig": {
|
|
33
|
+
"access": "public",
|
|
34
|
+
"provenance": true
|
|
35
|
+
},
|
|
36
|
+
"engines": {
|
|
37
|
+
"node": ">=24",
|
|
38
|
+
"npm": ">=11"
|
|
39
|
+
},
|
|
40
|
+
"scripts": {
|
|
41
|
+
"test": "vitest run",
|
|
42
|
+
"test:watch": "vitest",
|
|
43
|
+
"test:coverage": "vitest run --coverage",
|
|
44
|
+
"build": "rimraf dist && npx tsc --project tsconfig.json",
|
|
45
|
+
"postbuild": "chmod +x dist/main.js",
|
|
46
|
+
"start": "npm run build && npx @modelcontextprotocol/inspector node dist/main.js",
|
|
47
|
+
"dev": "concurrently \"npx tsc --watch\" \"npx @modelcontextprotocol/inspector npx nodemon --quiet --watch dist --ext js --exec node dist/main.js\"",
|
|
48
|
+
"type-check": "npx tsc --noEmit && npx tsc --noEmit -p .agents/scripts",
|
|
49
|
+
"format:check": "oxlint src scripts .agents/scripts *.config.js *.config.ts && oxfmt --check",
|
|
50
|
+
"format:fix": "oxlint src scripts .agents/scripts *.config.js *.config.ts --fix && oxfmt",
|
|
51
|
+
"prepublishOnly": "npm run build && npm test",
|
|
52
|
+
"prepare": "lefthook install --reset-hooks-path",
|
|
53
|
+
"verify": "node .agents/scripts/verify.ts",
|
|
54
|
+
"tool": "tsx scripts/run-tool.ts",
|
|
55
|
+
"tool:list": "tsx scripts/run-tool.ts --list",
|
|
56
|
+
"review:worktree": "node .agents/scripts/review-worktree.ts"
|
|
57
|
+
},
|
|
58
|
+
"dependencies": {
|
|
59
|
+
"@doist/comms-sdk": "3.12.0",
|
|
60
|
+
"@todoist/mcp-core": "1.0.0",
|
|
61
|
+
"dotenv": "17.4.2",
|
|
62
|
+
"p-limit": "6.2.0",
|
|
63
|
+
"zod": "4.6.7"
|
|
64
|
+
},
|
|
65
|
+
"peerDependencies": {
|
|
66
|
+
"@modelcontextprotocol/server": "^2.2.0"
|
|
67
|
+
},
|
|
68
|
+
"devDependencies": {
|
|
69
|
+
"@modelcontextprotocol/client": "2.3.0",
|
|
70
|
+
"@semantic-release/changelog": "6.0.3",
|
|
71
|
+
"@semantic-release/git": "10.0.1",
|
|
72
|
+
"@types/node": "22.19.17",
|
|
73
|
+
"@vitest/coverage-v8": "4.1.12",
|
|
74
|
+
"concurrently": "10.0.6",
|
|
75
|
+
"conventional-changelog-conventionalcommits": "9.3.1",
|
|
76
|
+
"gpt-tokenizer": "3.4.0",
|
|
77
|
+
"lefthook": "2.2.2",
|
|
78
|
+
"nodemon": "3.1.14",
|
|
79
|
+
"oxfmt": "0.72.0",
|
|
80
|
+
"oxlint": "1.63.0",
|
|
81
|
+
"rimraf": "6.1.3",
|
|
82
|
+
"semantic-release": "25.0.3",
|
|
83
|
+
"tsx": "4.22.4",
|
|
84
|
+
"typescript": "6.0.3",
|
|
85
|
+
"vitest": "4.1.12"
|
|
86
|
+
}
|
|
10
87
|
}
|