@todoist/automations-mcp 0.0.1 → 3.1.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/README.md CHANGED
@@ -1,45 +1,121 @@
1
- # @todoist/automations-mcp
2
-
3
- ## ⚠️ IMPORTANT NOTICE ⚠️
4
-
5
- **This package is created solely for the purpose of setting up OIDC (OpenID Connect) trusted publishing with npm.**
6
-
7
- This is **NOT** a functional package and contains **NO** code or functionality beyond the OIDC setup configuration.
8
-
9
- ## Purpose
10
-
11
- This package exists to:
12
- 1. Configure OIDC trusted publishing for the package name `@todoist/automations-mcp`
13
- 2. Enable secure, token-less publishing from CI/CD workflows
14
- 3. Establish provenance for packages published under this name
15
-
16
- ## What is OIDC Trusted Publishing?
17
-
18
- OIDC trusted publishing allows package maintainers to publish packages directly from their CI/CD workflows without needing to manage npm access tokens. Instead, it uses OpenID Connect to establish trust between the CI/CD provider (like GitHub Actions) and npm.
19
-
20
- ## Setup Instructions
21
-
22
- To properly configure OIDC trusted publishing for this package:
23
-
24
- 1. Go to [npmjs.com](https://www.npmjs.com/) and navigate to your package settings
25
- 2. Configure the trusted publisher (e.g., GitHub Actions)
26
- 3. Specify the repository and workflow that should be allowed to publish
27
- 4. Use the configured workflow to publish your actual package
28
-
29
- ## DO NOT USE THIS PACKAGE
30
-
31
- This package is a placeholder for OIDC configuration only. It:
32
- - Contains no executable code
33
- - Provides no functionality
34
- - Should not be installed as a dependency
35
- - Exists only for administrative purposes
36
-
37
- ## More Information
38
-
39
- For more details about npm's trusted publishing feature, see:
40
- - [npm Trusted Publishing Documentation](https://docs.npmjs.com/generating-provenance-statements)
41
- - [GitHub Actions OIDC Documentation](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect)
42
-
43
- ---
44
-
45
- **Maintained for OIDC setup purposes only**
1
+ # `@todoist/automations-mcp`
2
+
3
+ The MCP server for Todoist Automations: the tools that give an agent the same access to a user's
4
+ automations that the `tda` CLI gives, packaged for the hosted MCP server at `ai.todoist.net`. The
5
+ design and the rollout it is part of are in
6
+ [the spec](../../docs/specifications/automations-mcp-package.md).
7
+
8
+ ## What it exports
9
+
10
+ `getMcpServer({ token, baseUrl })` builds an `McpServer` over one user's Automations, bound to the
11
+ bearer token it is given: a delegated Todoist OAuth token with the `automations` audience, or a
12
+ Todoist personal token.
13
+
14
+ `validateAutomationsToken(token, baseUrl)` classifies a token before any tool runs, with one
15
+ status-only call to the automations list: `valid`, `invalid` (401) or `forbidden` (403 with an
16
+ `insufficient_scope` challenge). A 403 without that challenge counts as `valid` on purpose: it is a
17
+ refusal consent cannot lift, such as the waiting list, so each tool surfaces the backend's own
18
+ message instead of the client looping through OAuth. Any other status throws
19
+ `TokenValidationError` from `@todoist/mcp-core/host` with the status on it, which the hosted server
20
+ treats as transient for 5xx. Both functions follow the contract every Todoist MCP server shares, from
21
+ `@todoist/mcp-core/host`.
22
+
23
+ That is the whole published surface. The tools themselves are typed against
24
+ `@todoist/automations-sdk`, which is not published, so they are reached through the server rather than
25
+ exported, and the build refuses to emit a declaration that would leave a consumer with an import it
26
+ cannot resolve.
27
+
28
+ ## Chat turns
29
+
30
+ `start-conversation` and `continue-conversation` each run one durable server turn inside the tool
31
+ call, the way `tda chat` does in a process: the call blocks until the agent stops, which can take
32
+ minutes, and reports liveness every ten seconds through `notifications/progress` when the client
33
+ sent a progress token, or a debug log message otherwise. Cancelling the call aborts the upstream
34
+ turn; the partial reply is persisted and `continue-conversation` resumes it. The shared logic is
35
+ `@todoist/automations-sdk/chat-turn`, so the CLI and this package cannot drift on how a pending
36
+ action is read or a connection resolved.
37
+
38
+ ## Draft tests
39
+
40
+ `test-draft` starts a test run and, unless `waitMinutes` is 0, polls it until it ends or the wait
41
+ runs out, reporting progress every ten seconds the same way. A run still going at the limit keeps
42
+ running and `get-test-run` reads it later; a cancelled or failed wait names the run for the same
43
+ reason. The start, the polling and the outcome mapping are the SDK's `startDraftTest` and
44
+ `waitForDraftTest`, shared with `tda draft test`.
45
+
46
+ ## Running it locally
47
+
48
+ Everything here can run against a real account without the hosted server. `AUTOMATIONS_API_KEY` is
49
+ a Todoist personal token or the output of `tda auth token view`; `AUTOMATIONS_BASE_URL` points at
50
+ staging or a local backend and defaults to production, and `TODOIST_BASE_URL` points `get-usage` at
51
+ the same environment's Todoist API, where the balance lives (`https://staging.todoist.com/api` for
52
+ staging).
53
+
54
+ ```bash
55
+ npm run build:core # once, from the monorepo root
56
+ npm run build:mcp # produces apps/mcp/dist
57
+ npm --workspace=apps/mcp run inspect # the MCP inspector over stdio
58
+ npm --workspace=apps/mcp run tool -- find-automations '{"limit": 5}'
59
+ npm --workspace=apps/mcp run tool -- start-conversation '{"message": "Draft an automation that..."}'
60
+ npm --workspace=apps/mcp run tool:list
61
+ ```
62
+
63
+ An MCP client can point at the stdio build directly, with the same environment:
64
+
65
+ ```json
66
+ {
67
+ "mcpServers": {
68
+ "automations": {
69
+ "command": "node",
70
+ "args": ["/path/to/automations/apps/mcp/dist/main.js"],
71
+ "env": { "AUTOMATIONS_API_KEY": "..." }
72
+ }
73
+ }
74
+ }
75
+ ```
76
+
77
+ ## Releases
78
+
79
+ Versions before 3.0.0 were published as `@doist/automations-mcp`.
80
+
81
+ `@todoist/automations-mcp` is published from `main` by
82
+ [`.github/workflows/release-mcp.yml`](../../.github/workflows/release-mcp.yml), which runs
83
+ semantic-release with the configuration in [`release.config.js`](./release.config.js). The version
84
+ comes from the conventional-commit messages of the commits that count towards this package, so
85
+ nothing is bumped by hand and the repository holds no version number of its own. The same commits
86
+ make up the release notes and the Comms announcement. Releases go to the `latest` dist tag:
87
+ the consumer is the hosted server, which pins an exact version. After publishing, the workflow sends
88
+ an `automations-mcp-updated` dispatch to `todoist/todoist-ai-integrations`, whose update workflow
89
+ installs the version, runs its checks, commits and redeploys, so a release reaches `ai.todoist.net`
90
+ without waiting for a dependency PR.
91
+
92
+ The workspace libraries the package uses are not published, so `npm run build` compiles them into
93
+ `dist/` and only the packages under `dependencies` stay external. Any change here counts, except
94
+ tests, docs and `package.json` fields that don't change what gets installed. `packages/sdk`,
95
+ `packages/core` and `packages/bitmapist` are shared with the backend and the web app, so a change
96
+ confined to them counts only when its commit is scoped `mcp` or `sdk`. Any other change there still
97
+ ships, with the next release. See
98
+ [Published packages](../../docs/standards/commit-guidelines.md#published-packages) for how to split
99
+ pull requests so each change lands in the right release.
100
+
101
+ ## Adding a tool
102
+
103
+ `src/tool-registry.ts` is the single source of truth for the tool surface; the server, `run-tool`
104
+ and the token-footprint baseline derive from it, and `src/tool-registry.test.ts` fails when the
105
+ views drift.
106
+
107
+ 1. `src/utils/tool-names.ts`: add the name.
108
+ 2. `src/tools/<tool-name>.ts`: the definition, `satisfies AutomationsTool<...>`. Copy
109
+ `find-automations.ts`.
110
+ 3. `src/tool-registry.ts`: add it to the map, in the section it belongs to.
111
+ 4. `src/tools/tool-annotations.test.ts`: add its annotation expectation.
112
+ 5. `src/tools/<tool-name>.test.ts`: tests against a faked `AutomationsApi`.
113
+ 6. `src/mcp-server.ts`: add to `instructions` only when the tool needs cross-tool routing
114
+ guidance; per-tool detail belongs in its own description.
115
+
116
+ Output schemas never use `.nullable()`: nulls are stripped before the SDK validates the output, so
117
+ a nullable field is a validation failure waiting to happen. Use `.optional()` and leave the key
118
+ out. `src/tools/output-schema-nullability.test.ts` enforces it.
119
+
120
+ `src/token-footprint.test.ts` prints what the tool surface costs a model on every `tools/list`. If a
121
+ change pushes the combined fixed cost over its budget, raise the budget in the same PR and say so.