@doist/automations-mcp 1.0.0 → 1.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 +4 -1
- package/dist/{chunk-WN2JU6T5.js → chunk-BU6WJ7QM.js} +232 -80
- package/dist/chunk-BU6WJ7QM.js.map +7 -0
- package/dist/index.js +1 -1
- package/dist/main.js +1 -1
- package/dist/mcp-server.d.ts +1 -1
- package/package.json +2 -2
- package/dist/chunk-WN2JU6T5.js.map +0 -7
package/README.md
CHANGED
|
@@ -70,7 +70,10 @@ An MCP client can point at the stdio build directly, with the same environment:
|
|
|
70
70
|
semantic-release with the configuration in [`release.config.js`](./release.config.js). The version
|
|
71
71
|
comes from the conventional-commit messages that touched this directory, so nothing is bumped by
|
|
72
72
|
hand and the repository holds no version number of its own. Releases go to the `latest` dist tag:
|
|
73
|
-
the consumer is the hosted server, which pins an exact version
|
|
73
|
+
the consumer is the hosted server, which pins an exact version. After publishing, the workflow sends
|
|
74
|
+
an `automations-mcp-updated` dispatch to `Doist/todoist-ai-integrations`, whose update workflow
|
|
75
|
+
installs the version, runs its checks, commits and redeploys, so a release reaches `ai.todoist.net`
|
|
76
|
+
without waiting for a dependency PR.
|
|
74
77
|
|
|
75
78
|
The workspace libraries the package uses are not published, so `npm run build` compiles them into
|
|
76
79
|
`dist/` and only the packages under `dependencies` stay external. Because a release is scoped to
|
|
@@ -131,6 +131,81 @@ var WEBHOOK_SIGNATURE_TOLERANCE_SECONDS = 5 * 60;
|
|
|
131
131
|
var WEBHOOK_SUBSCRIPTION_STATUSES = ["active", "paused", "error"];
|
|
132
132
|
var PROVIDER_TYPES = ["direct", "pubsub", "app-level"];
|
|
133
133
|
|
|
134
|
+
// ../../packages/core/dist/esm/models.js
|
|
135
|
+
var MODEL_CATALOG = {
|
|
136
|
+
"gemini-2.5-flash-lite": {
|
|
137
|
+
provider: "gemini",
|
|
138
|
+
family: "2.5",
|
|
139
|
+
providerModelId: "gemini-2.5-flash-lite"
|
|
140
|
+
},
|
|
141
|
+
"gemini-2.5-flash": {
|
|
142
|
+
provider: "gemini",
|
|
143
|
+
family: "2.5",
|
|
144
|
+
providerModelId: "gemini-2.5-flash"
|
|
145
|
+
},
|
|
146
|
+
"gemini-3.1-pro": {
|
|
147
|
+
provider: "gemini",
|
|
148
|
+
family: "3",
|
|
149
|
+
providerModelId: "gemini-3.1-pro-preview"
|
|
150
|
+
},
|
|
151
|
+
"gemini-3.8-flash": {
|
|
152
|
+
provider: "gemini",
|
|
153
|
+
family: "3",
|
|
154
|
+
providerModelId: "gemini-3.8-flash"
|
|
155
|
+
},
|
|
156
|
+
"claude-opus-4-6": {
|
|
157
|
+
provider: "anthropic",
|
|
158
|
+
family: "4.6",
|
|
159
|
+
providerModelId: "claude-opus-4-6"
|
|
160
|
+
},
|
|
161
|
+
"claude-sonnet-5": {
|
|
162
|
+
provider: "anthropic",
|
|
163
|
+
family: "5",
|
|
164
|
+
providerModelId: "claude-sonnet-5"
|
|
165
|
+
},
|
|
166
|
+
"claude-sonnet-4-6": {
|
|
167
|
+
provider: "anthropic",
|
|
168
|
+
family: "4.6",
|
|
169
|
+
providerModelId: "claude-sonnet-4-6"
|
|
170
|
+
},
|
|
171
|
+
"claude-haiku-4-5": {
|
|
172
|
+
provider: "anthropic",
|
|
173
|
+
family: "4.5",
|
|
174
|
+
providerModelId: "claude-haiku-4-5"
|
|
175
|
+
},
|
|
176
|
+
"deepseek-v4-flash": {
|
|
177
|
+
provider: "openrouter",
|
|
178
|
+
family: "deepseek",
|
|
179
|
+
providerModelId: "deepseek/deepseek-v4-flash-0731"
|
|
180
|
+
},
|
|
181
|
+
"deepseek-v4-pro": {
|
|
182
|
+
provider: "openrouter",
|
|
183
|
+
family: "deepseek",
|
|
184
|
+
providerModelId: "deepseek/deepseek-v4-pro"
|
|
185
|
+
},
|
|
186
|
+
"mimo-v2.5": {
|
|
187
|
+
provider: "openrouter",
|
|
188
|
+
family: "mimo",
|
|
189
|
+
providerModelId: "xiaomi/mimo-v2.5"
|
|
190
|
+
},
|
|
191
|
+
"mimo-v2.5-pro": {
|
|
192
|
+
provider: "openrouter",
|
|
193
|
+
family: "mimo",
|
|
194
|
+
providerModelId: "xiaomi/mimo-v2.5-pro"
|
|
195
|
+
},
|
|
196
|
+
"glm-5.2": {
|
|
197
|
+
provider: "openrouter",
|
|
198
|
+
family: "glm",
|
|
199
|
+
providerModelId: "z-ai/glm-5.2"
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
var SUPPORTED_LLM_MODELS = Object.keys(MODEL_CATALOG);
|
|
203
|
+
var SUPPORTED_SEARCH_MODELS = SUPPORTED_LLM_MODELS.filter(supportsWebSearch);
|
|
204
|
+
function supportsWebSearch(modelId) {
|
|
205
|
+
const { provider } = MODEL_CATALOG[modelId];
|
|
206
|
+
return provider === "gemini" || provider === "anthropic";
|
|
207
|
+
}
|
|
208
|
+
|
|
134
209
|
// ../../packages/core/dist/esm/schemas/admin.schema.js
|
|
135
210
|
import { z } from "zod";
|
|
136
211
|
var AdminAccessResponseSchema = z.object({
|
|
@@ -1181,21 +1256,16 @@ var baseStepSchema = z7.object({
|
|
|
1181
1256
|
description: "Overrides the global execution policy (timeout and retries) for this step."
|
|
1182
1257
|
})
|
|
1183
1258
|
});
|
|
1184
|
-
var
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
"
|
|
1188
|
-
|
|
1189
|
-
"claude-sonnet-4-6"
|
|
1190
|
-
];
|
|
1191
|
-
var DEFAULT_LLM_MODEL = "claude-haiku-4-5";
|
|
1259
|
+
var MODEL_TIERS = ["lite", "flash", "pro"];
|
|
1260
|
+
var SUPPORTED_MODEL_REFERENCES = [...MODEL_TIERS, ...SUPPORTED_LLM_MODELS];
|
|
1261
|
+
var modelReferenceSchema = z7.enum(SUPPORTED_MODEL_REFERENCES).meta({
|
|
1262
|
+
description: "A stable model tier (lite, flash, pro) or a supported literal model override."
|
|
1263
|
+
});
|
|
1192
1264
|
var llmStepSchema = baseStepSchema.merge(z7.object({
|
|
1193
1265
|
type: z7.literal("llm"),
|
|
1194
1266
|
prompt: z7.string().meta({ description: "The prompt template to be sent to the LLM." }),
|
|
1195
1267
|
outputSchema: stepOutputSchema,
|
|
1196
|
-
model:
|
|
1197
|
-
description: `The specific model to use. Supported models: ${SUPPORTED_LLM_MODELS.join(", ")}.`
|
|
1198
|
-
}),
|
|
1268
|
+
model: modelReferenceSchema,
|
|
1199
1269
|
tools: z7.record(z7.string(), z7.array(z7.string())).default({}).meta({
|
|
1200
1270
|
description: 'A mapping from MCP server connector IDs to arrays of their tool names (e.g., {"todoist": ["find-tasks-by-date"], "linear": ["create-issue"]}).'
|
|
1201
1271
|
})
|
|
@@ -1206,9 +1276,7 @@ var codegenStepSchema = baseStepSchema.merge(z7.object({
|
|
|
1206
1276
|
description: "The goal or instruction for what the generated code should accomplish."
|
|
1207
1277
|
}),
|
|
1208
1278
|
outputSchema: stepOutputSchema,
|
|
1209
|
-
model:
|
|
1210
|
-
description: `The specific model to use for code generation. Supported models: ${SUPPORTED_LLM_MODELS.join(", ")}.`
|
|
1211
|
-
}),
|
|
1279
|
+
model: modelReferenceSchema,
|
|
1212
1280
|
tools: z7.record(z7.string(), z7.array(z7.string())).default({}).meta({
|
|
1213
1281
|
description: 'A mapping from MCP server connector IDs to arrays of their tool names that will be available in the generated code (e.g., {"todoist": ["find-tasks", "update-tasks"]}).'
|
|
1214
1282
|
}),
|
|
@@ -1245,8 +1313,8 @@ var searchStepSchema = baseStepSchema.merge(z7.object({
|
|
|
1245
1313
|
description: "The search prompt to execute using web search."
|
|
1246
1314
|
}),
|
|
1247
1315
|
outputSchema: searchStepOutputSchema,
|
|
1248
|
-
model: z7.enum(
|
|
1249
|
-
description:
|
|
1316
|
+
model: z7.enum([...MODEL_TIERS, ...SUPPORTED_SEARCH_MODELS]).optional().meta({
|
|
1317
|
+
description: "A stable tier (lite, flash, pro) or a supported search-enabled literal model override."
|
|
1250
1318
|
})
|
|
1251
1319
|
}));
|
|
1252
1320
|
var delayStepOutputSchema = z7.object({
|
|
@@ -1554,8 +1622,8 @@ function validateManifestResultFrom(data, ctx) {
|
|
|
1554
1622
|
});
|
|
1555
1623
|
return;
|
|
1556
1624
|
}
|
|
1557
|
-
const
|
|
1558
|
-
if (!
|
|
1625
|
+
const outputSchema21 = referencedStep.outputSchema;
|
|
1626
|
+
if (!outputSchema21) {
|
|
1559
1627
|
ctx.addIssue({
|
|
1560
1628
|
code: z7.ZodIssueCode.custom,
|
|
1561
1629
|
message: `resultFrom.stepId references step "${referencedStep.id}" without an outputSchema.`,
|
|
@@ -1564,7 +1632,7 @@ function validateManifestResultFrom(data, ctx) {
|
|
|
1564
1632
|
return;
|
|
1565
1633
|
}
|
|
1566
1634
|
if (!data.resultFrom.path) {
|
|
1567
|
-
if (!isPlainStringSchema(
|
|
1635
|
+
if (!isPlainStringSchema(outputSchema21)) {
|
|
1568
1636
|
ctx.addIssue({
|
|
1569
1637
|
code: z7.ZodIssueCode.custom,
|
|
1570
1638
|
message: "resultFrom.path may be omitted only when the referenced step outputSchema is a string.",
|
|
@@ -1574,7 +1642,7 @@ function validateManifestResultFrom(data, ctx) {
|
|
|
1574
1642
|
return;
|
|
1575
1643
|
}
|
|
1576
1644
|
const propertyPath = data.resultFrom.path.split(".");
|
|
1577
|
-
const resolvedSchema = resolvePropertySchemaInSchema(
|
|
1645
|
+
const resolvedSchema = resolvePropertySchemaInSchema(outputSchema21, propertyPath);
|
|
1578
1646
|
if (!resolvedSchema) {
|
|
1579
1647
|
ctx.addIssue({
|
|
1580
1648
|
code: z7.ZodIssueCode.custom,
|
|
@@ -1623,11 +1691,11 @@ function validateIfConditionLiteral({ condition, context, stepId }) {
|
|
|
1623
1691
|
const referencedStepId = parts[1];
|
|
1624
1692
|
if (!referencedStepId)
|
|
1625
1693
|
return null;
|
|
1626
|
-
const
|
|
1627
|
-
if (!
|
|
1694
|
+
const outputSchema21 = context.steps.get(referencedStepId);
|
|
1695
|
+
if (!outputSchema21)
|
|
1628
1696
|
return null;
|
|
1629
1697
|
const propertyPath = parts.slice(2);
|
|
1630
|
-
const resolved = propertyPath.length === 0 ?
|
|
1698
|
+
const resolved = propertyPath.length === 0 ? outputSchema21 : resolvePropertySchemaInSchema(outputSchema21, propertyPath);
|
|
1631
1699
|
if (!resolved)
|
|
1632
1700
|
return null;
|
|
1633
1701
|
return ifConditionLiteralError({ reference, literal, stepId, schema: resolved });
|
|
@@ -3142,17 +3210,18 @@ var AuthorizeUsageRequestSchema = z33.object({
|
|
|
3142
3210
|
category: z33.string().min(1).max(CATEGORY_MAX_LENGTH)
|
|
3143
3211
|
});
|
|
3144
3212
|
var UsageBillingUnitsSchema = z33.number().int().nonnegative();
|
|
3213
|
+
var UsageBillingBalanceSchema = z33.number().int();
|
|
3145
3214
|
var RecordUsageRefsSchema = z33.record(z33.string().max(40), z33.string().max(500)).refine((refs) => Object.keys(refs).length <= 50);
|
|
3146
3215
|
var AuthorizeUsageResponseSchema = z33.discriminatedUnion("decision", [
|
|
3147
3216
|
z33.object({
|
|
3148
3217
|
decision: z33.literal("allowed"),
|
|
3149
3218
|
reservation_id: z33.string().min(1),
|
|
3150
|
-
available_units:
|
|
3219
|
+
available_units: UsageBillingBalanceSchema
|
|
3151
3220
|
}),
|
|
3152
3221
|
z33.object({
|
|
3153
3222
|
decision: z33.literal("denied"),
|
|
3154
3223
|
reason: z33.enum(["insufficient_credit", "no_billing_account"]),
|
|
3155
|
-
available_units:
|
|
3224
|
+
available_units: UsageBillingBalanceSchema
|
|
3156
3225
|
})
|
|
3157
3226
|
]);
|
|
3158
3227
|
var RecordUsageRequestSchema = z33.object({
|
|
@@ -3169,7 +3238,7 @@ var RecordUsageRequestSchema = z33.object({
|
|
|
3169
3238
|
var RecordUsageResponseSchema = z33.object({
|
|
3170
3239
|
recorded: z33.boolean(),
|
|
3171
3240
|
charged_units: UsageBillingUnitsSchema,
|
|
3172
|
-
available_units:
|
|
3241
|
+
available_units: UsageBillingBalanceSchema
|
|
3173
3242
|
});
|
|
3174
3243
|
var TOP_UP_USD_MIN_AMOUNT = 500;
|
|
3175
3244
|
var TopUpCurrencySchema = z33.preprocess((value) => typeof value === "string" ? value.toLowerCase() : value, z33.literal("usd"));
|
|
@@ -3191,8 +3260,8 @@ var BillingPortalUrlResponseSchema = z33.object({
|
|
|
3191
3260
|
billing_portal_url: z33.url()
|
|
3192
3261
|
});
|
|
3193
3262
|
var ReadStateResponseSchema = z33.object({
|
|
3194
|
-
available_units:
|
|
3195
|
-
available_amount:
|
|
3263
|
+
available_units: UsageBillingBalanceSchema,
|
|
3264
|
+
available_amount: UsageBillingBalanceSchema,
|
|
3196
3265
|
currency: z33.string(),
|
|
3197
3266
|
usage_allowed: z33.boolean(),
|
|
3198
3267
|
low_balance: z33.boolean(),
|
|
@@ -5818,7 +5887,7 @@ import { McpServer } from "@modelcontextprotocol/server";
|
|
|
5818
5887
|
// package.json
|
|
5819
5888
|
var package_default = {
|
|
5820
5889
|
name: "@doist/automations-mcp",
|
|
5821
|
-
version: "1.
|
|
5890
|
+
version: "1.1.0",
|
|
5822
5891
|
description: "MCP server and importable AI tools for Todoist Automations",
|
|
5823
5892
|
type: "module",
|
|
5824
5893
|
main: "./dist/index.js",
|
|
@@ -5875,7 +5944,7 @@ var package_default = {
|
|
|
5875
5944
|
"@doist/automations-sdk": "*",
|
|
5876
5945
|
"@modelcontextprotocol/client": "2.0.0",
|
|
5877
5946
|
"@modelcontextprotocol/server": "2.0.0",
|
|
5878
|
-
"@types/node": "24.13.
|
|
5947
|
+
"@types/node": "24.13.5",
|
|
5879
5948
|
"conventional-changelog-conventionalcommits": "9.3.1",
|
|
5880
5949
|
esbuild: "0.28.2",
|
|
5881
5950
|
"gpt-tokenizer": "4.0.0",
|
|
@@ -6034,7 +6103,7 @@ function registerTool({
|
|
|
6034
6103
|
transport
|
|
6035
6104
|
}) {
|
|
6036
6105
|
const execute = tool.execute;
|
|
6037
|
-
const { input: inputSchema, output:
|
|
6106
|
+
const { input: inputSchema, output: outputSchema21 } = getToolSchemas(tool);
|
|
6038
6107
|
const callback = async (args, ctx) => {
|
|
6039
6108
|
try {
|
|
6040
6109
|
const { textContent, structuredContent } = await execute(args, {
|
|
@@ -6061,7 +6130,7 @@ function registerTool({
|
|
|
6061
6130
|
{
|
|
6062
6131
|
description: tool.description,
|
|
6063
6132
|
inputSchema,
|
|
6064
|
-
...
|
|
6133
|
+
...outputSchema21 ? { outputSchema: outputSchema21 } : {},
|
|
6065
6134
|
annotations: getMcpAnnotations(tool)
|
|
6066
6135
|
},
|
|
6067
6136
|
callback
|
|
@@ -6163,6 +6232,9 @@ var automationSummarySchema = z60.object({
|
|
|
6163
6232
|
visibility: z60.enum(AUTOMATION_VISIBILITIES),
|
|
6164
6233
|
isOwner: z60.boolean(),
|
|
6165
6234
|
workspaceId: z60.string().optional().describe("Absent for personal automations."),
|
|
6235
|
+
updatedBy: z60.string().optional().describe(
|
|
6236
|
+
"The Todoist user id of whoever last changed the automation, which in a workspace can be an admin rather than the creator. Absent until someone has changed it."
|
|
6237
|
+
),
|
|
6166
6238
|
disabledReason: z60.enum(AUTOMATION_DISABLED_REASONS).optional().describe(
|
|
6167
6239
|
"Present when the system, not the user, disabled it; it cannot be enabled until fixed."
|
|
6168
6240
|
),
|
|
@@ -6391,6 +6463,7 @@ function summarizeAutomationForList(dto) {
|
|
|
6391
6463
|
visibility: automation.visibility,
|
|
6392
6464
|
isOwner: automation.isOwner,
|
|
6393
6465
|
...automation.workspaceId ? { workspaceId: automation.workspaceId } : {},
|
|
6466
|
+
...automation.updatedBy ? { updatedBy: automation.updatedBy } : {},
|
|
6394
6467
|
...automation.disabledReason ? { disabledReason: automation.disabledReason } : {},
|
|
6395
6468
|
triggers: triggers.flatMap((trigger) => summarizeTrigger(trigger) ?? []),
|
|
6396
6469
|
connections: automation.connections.map((connection) => ({
|
|
@@ -6643,6 +6716,8 @@ var ToolNames = {
|
|
|
6643
6716
|
// Mutation
|
|
6644
6717
|
UPDATE_AUTOMATION: "update-automation",
|
|
6645
6718
|
SET_AUTOMATION_SCHEDULE: "set-automation-schedule",
|
|
6719
|
+
SET_AUTOMATION_VISIBILITY: "set-automation-visibility",
|
|
6720
|
+
MOVE_AUTOMATION: "move-automation",
|
|
6646
6721
|
TRIGGER_AUTOMATION: "trigger-automation",
|
|
6647
6722
|
// Connection
|
|
6648
6723
|
CONNECT_SERVICE: "connect-service",
|
|
@@ -6969,6 +7044,10 @@ import { z as z66 } from "zod";
|
|
|
6969
7044
|
var workspaceIdParameter = z66.string().optional().describe(
|
|
6970
7045
|
"Act on this Todoist workspace. Omit for the personal space. The two are separate: a workspace automation is not found in the personal space, and vice versa."
|
|
6971
7046
|
);
|
|
7047
|
+
var requiredWorkspaceIdParameter = z66.string().describe("The Todoist workspace, as returned by list-workspaces.");
|
|
7048
|
+
function describeVisibility(visibility) {
|
|
7049
|
+
return visibility === "workspace" ? "visible to the workspace" : "private to its creator";
|
|
7050
|
+
}
|
|
6972
7051
|
function describeScope(workspaceId) {
|
|
6973
7052
|
return workspaceId === void 0 ? "personal" : `workspace ${workspaceId}`;
|
|
6974
7053
|
}
|
|
@@ -7443,36 +7522,69 @@ var listWorkspaces = {
|
|
|
7443
7522
|
}
|
|
7444
7523
|
};
|
|
7445
7524
|
|
|
7446
|
-
// src/tools/
|
|
7525
|
+
// src/tools/move-automation.ts
|
|
7447
7526
|
import { z as z78 } from "zod";
|
|
7448
7527
|
var parameters16 = {
|
|
7449
|
-
|
|
7528
|
+
automationId: z78.string().describe(
|
|
7529
|
+
"The id of the automation to move, as returned by find-automations. It may be a personal automation or one in another workspace."
|
|
7530
|
+
),
|
|
7531
|
+
workspaceId: z78.string().describe("The workspace to move it into, as returned by list-workspaces."),
|
|
7532
|
+
visibility: z78.enum(AUTOMATION_VISIBILITIES).optional().describe(
|
|
7533
|
+
'How the automation is shared once moved. Defaults to "workspace", visible to every member; "private" keeps it to its creator.'
|
|
7534
|
+
)
|
|
7535
|
+
};
|
|
7536
|
+
var outputSchema15 = { automation: automationSummarySchema };
|
|
7537
|
+
var moveAutomation = {
|
|
7538
|
+
name: ToolNames.MOVE_AUTOMATION,
|
|
7539
|
+
description: "Moves an automation the user created into a workspace, from their personal space or from another workspace they can still use. It keeps running on the creator\u2019s own connections, and any unpublished edits move with it. The destination is always a workspace: nothing moves back to the personal space. Fails when the user did not create the automation, or when the workspace it is in now no longer includes them or Automations. Takes effect immediately with no confirmation of its own, so confirm intent with the user first.",
|
|
7540
|
+
parameters: parameters16,
|
|
7541
|
+
outputSchema: outputSchema15,
|
|
7542
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true },
|
|
7543
|
+
async execute({ automationId, workspaceId, visibility }, { api, signal }) {
|
|
7544
|
+
const dto = await api.workspaceAutomations.move(
|
|
7545
|
+
workspaceId,
|
|
7546
|
+
automationId,
|
|
7547
|
+
visibility === void 0 ? {} : { visibility },
|
|
7548
|
+
{ signal }
|
|
7549
|
+
);
|
|
7550
|
+
const automation = summarizeAutomationForList(dto);
|
|
7551
|
+
return {
|
|
7552
|
+
textContent: `Moved "${automation.name}" to workspace ${workspaceId}; it is now ${describeVisibility(automation.visibility)}.`,
|
|
7553
|
+
structuredContent: { automation }
|
|
7554
|
+
};
|
|
7555
|
+
}
|
|
7556
|
+
};
|
|
7557
|
+
|
|
7558
|
+
// src/tools/repair-connection.ts
|
|
7559
|
+
import { z as z79 } from "zod";
|
|
7560
|
+
var parameters17 = {
|
|
7561
|
+
connectionId: z79.string().describe(
|
|
7450
7562
|
"The connection to repair, as listed by get-connector or reported by check-connection."
|
|
7451
7563
|
)
|
|
7452
7564
|
};
|
|
7453
|
-
var
|
|
7454
|
-
connectionId:
|
|
7455
|
-
connectorId:
|
|
7456
|
-
serviceName:
|
|
7457
|
-
resumed:
|
|
7565
|
+
var outputSchema16 = {
|
|
7566
|
+
connectionId: z79.string().describe("The connection to pass to check-connection next."),
|
|
7567
|
+
connectorId: z79.string(),
|
|
7568
|
+
serviceName: z79.string(),
|
|
7569
|
+
resumed: z79.boolean().describe(
|
|
7458
7570
|
"True when the existing pending setup was returned; false when a replacement was started."
|
|
7459
7571
|
),
|
|
7460
|
-
replacedConnectionId:
|
|
7572
|
+
replacedConnectionId: z79.string().optional().describe(
|
|
7461
7573
|
"The broken connection the replacement stands in for. Present when resumed is false."
|
|
7462
7574
|
),
|
|
7463
|
-
status:
|
|
7575
|
+
status: z79.enum(["pending", "authorized"]).describe(
|
|
7464
7576
|
'"pending" until the user completes the setup; "authorized" when nothing was needed.'
|
|
7465
7577
|
),
|
|
7466
7578
|
setup: connectionSetupSchema.optional().describe("What the user must complete. Absent when authorized."),
|
|
7467
|
-
automations:
|
|
7579
|
+
automations: z79.array(affectedAutomationSchema).optional().describe(
|
|
7468
7580
|
"Personal automations that move to the replacement once it is authorised. Present when resumed is false."
|
|
7469
7581
|
)
|
|
7470
7582
|
};
|
|
7471
7583
|
var repairConnection = {
|
|
7472
7584
|
name: ToolNames.REPAIR_CONNECTION,
|
|
7473
7585
|
description: "Fixes a connection that is not authorised. A pending one gets its setup returned again; an expired, errored or stale one is replaced by a new connection that the personal automations using it move to once the user authorises it. Returns what the user must complete, never waits, and tells you which connectionId to pass to check-connection.",
|
|
7474
|
-
parameters:
|
|
7475
|
-
outputSchema:
|
|
7586
|
+
parameters: parameters17,
|
|
7587
|
+
outputSchema: outputSchema16,
|
|
7476
7588
|
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false },
|
|
7477
7589
|
async execute({ connectionId }, { api, signal }) {
|
|
7478
7590
|
const options = { signal };
|
|
@@ -7527,26 +7639,26 @@ var repairConnection = {
|
|
|
7527
7639
|
};
|
|
7528
7640
|
|
|
7529
7641
|
// src/tools/set-automation-schedule.ts
|
|
7530
|
-
import { z as
|
|
7531
|
-
var
|
|
7532
|
-
automationId:
|
|
7642
|
+
import { z as z80 } from "zod";
|
|
7643
|
+
var parameters18 = {
|
|
7644
|
+
automationId: z80.string().describe("The id of the automation, as returned by find-automations."),
|
|
7533
7645
|
workspaceId: workspaceIdParameter,
|
|
7534
|
-
cron:
|
|
7646
|
+
cron: z80.string().optional().describe(
|
|
7535
7647
|
'A five-part cron expression such as "0 9 * * 1-5". Requires timezone. Use this or interval, not both.'
|
|
7536
7648
|
),
|
|
7537
|
-
timezone:
|
|
7649
|
+
timezone: z80.string().optional().describe(
|
|
7538
7650
|
'The IANA zone the cron expression is read in, such as "Europe/London". Only with cron.'
|
|
7539
7651
|
),
|
|
7540
|
-
interval:
|
|
7652
|
+
interval: z80.string().optional().describe(
|
|
7541
7653
|
'How often to run, as a number and unit: "45m", "6h", "1d", "1w". Use this or cron, not both.'
|
|
7542
7654
|
)
|
|
7543
7655
|
};
|
|
7544
|
-
var
|
|
7656
|
+
var outputSchema17 = { automation: automationSummarySchema };
|
|
7545
7657
|
var setAutomationSchedule = {
|
|
7546
7658
|
name: ToolNames.SET_AUTOMATION_SCHEDULE,
|
|
7547
7659
|
description: 'Changes when a schedule-triggered automation runs, as either a cron expression with a timezone or a fixed interval. Natural language such as "every weekday morning" is not accepted; translate it first. Takes effect immediately with no confirmation of its own, so confirm intent with the user first. Fails for automations that run on events or API calls.',
|
|
7548
|
-
parameters:
|
|
7549
|
-
outputSchema:
|
|
7660
|
+
parameters: parameters18,
|
|
7661
|
+
outputSchema: outputSchema17,
|
|
7550
7662
|
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true },
|
|
7551
7663
|
async execute({ automationId, workspaceId, cron, timezone, interval }, { api, signal }) {
|
|
7552
7664
|
const value = resolveScheduleInput(
|
|
@@ -7569,21 +7681,55 @@ var setAutomationSchedule = {
|
|
|
7569
7681
|
}
|
|
7570
7682
|
};
|
|
7571
7683
|
|
|
7684
|
+
// src/tools/set-automation-visibility.ts
|
|
7685
|
+
import { z as z81 } from "zod";
|
|
7686
|
+
var parameters19 = {
|
|
7687
|
+
automationId: z81.string().describe("The id of the automation, as returned by find-automations."),
|
|
7688
|
+
workspaceId: requiredWorkspaceIdParameter,
|
|
7689
|
+
visibility: z81.enum(AUTOMATION_VISIBILITIES).describe(
|
|
7690
|
+
'"workspace": every member can see and run it. "private": only its creator can see it, workspace admins included.'
|
|
7691
|
+
)
|
|
7692
|
+
};
|
|
7693
|
+
var outputSchema18 = { automation: automationSummarySchema };
|
|
7694
|
+
var setAutomationVisibility = {
|
|
7695
|
+
name: ToolNames.SET_AUTOMATION_VISIBILITY,
|
|
7696
|
+
description: "Shares a workspace automation with the whole workspace, or takes it back to private. Only the creator can change it, or a workspace admin while it is team-visible; once private it is out of every admin\u2019s reach until the creator shares it again. Takes effect immediately with no confirmation of its own, so confirm intent with the user first. Workspace automations only: a personal automation has no team to be visible to.",
|
|
7697
|
+
parameters: parameters19,
|
|
7698
|
+
outputSchema: outputSchema18,
|
|
7699
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true },
|
|
7700
|
+
async execute({ automationId, workspaceId, visibility }, { api, signal }) {
|
|
7701
|
+
const dto = await api.workspaceAutomations.updateVisibility(
|
|
7702
|
+
workspaceId,
|
|
7703
|
+
automationId,
|
|
7704
|
+
{ visibility },
|
|
7705
|
+
{ signal }
|
|
7706
|
+
);
|
|
7707
|
+
const automation = summarizeAutomationForList(dto);
|
|
7708
|
+
return {
|
|
7709
|
+
textContent: `"${automation.name}" is now ${describeVisibility(automation.visibility)}.`,
|
|
7710
|
+
structuredContent: { automation }
|
|
7711
|
+
};
|
|
7712
|
+
}
|
|
7713
|
+
};
|
|
7714
|
+
|
|
7572
7715
|
// src/tools/start-conversation.ts
|
|
7573
|
-
import { z as
|
|
7574
|
-
var
|
|
7575
|
-
|
|
7716
|
+
import { z as z82 } from "zod";
|
|
7717
|
+
var parameters20 = {
|
|
7718
|
+
workspaceId: workspaceIdParameter.describe(
|
|
7719
|
+
"Author the automation in this Todoist workspace: the conversation, its draft and the published automation all belong there, and continue-conversation follows it automatically. Omit for the personal space."
|
|
7720
|
+
),
|
|
7721
|
+
message: z82.string().min(1).describe(
|
|
7576
7722
|
"What the user wants automated, in their words. Say whether the automation should be published or left as a draft; the agent otherwise asks."
|
|
7577
7723
|
)
|
|
7578
7724
|
};
|
|
7579
7725
|
var startConversation = {
|
|
7580
7726
|
name: ToolNames.START_CONVERSATION,
|
|
7581
|
-
description: "Creates a conversation with the Automations agent and runs its first turn: the agent designs an automation from the message, asks questions, or asks for service connections. Blocks until the turn ends, which can take minutes; progress is reported meanwhile. Returns the conversationId to continue with and the outcome: awaiting_input (reply with continue-conversation), action_required (resolve pendingAction first) or published.
|
|
7582
|
-
parameters:
|
|
7727
|
+
description: "Creates a conversation with the Automations agent and runs its first turn: the agent designs an automation from the message, asks questions, or asks for service connections. Blocks until the turn ends, which can take minutes; progress is reported meanwhile. Returns the conversationId to continue with and the outcome: awaiting_input (reply with continue-conversation), action_required (resolve pendingAction first) or published. Runs on the user\u2019s own connections in either space.",
|
|
7728
|
+
parameters: parameters20,
|
|
7583
7729
|
outputSchema: turnResultSchema,
|
|
7584
7730
|
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false },
|
|
7585
|
-
async execute({ message }, { api, transport, signal, reportProgress }) {
|
|
7586
|
-
const conversation = await api.chat.createConversation({}, { signal });
|
|
7731
|
+
async execute({ workspaceId, message }, { api, transport, signal, reportProgress }) {
|
|
7732
|
+
const conversation = workspaceId === void 0 ? await api.chat.createConversation({}, { signal }) : await api.workspaceChat.createConversation(workspaceId, {}, { signal });
|
|
7587
7733
|
const result = summarizeTurnResult(
|
|
7588
7734
|
await runTurn({
|
|
7589
7735
|
api,
|
|
@@ -7602,21 +7748,21 @@ var startConversation = {
|
|
|
7602
7748
|
};
|
|
7603
7749
|
|
|
7604
7750
|
// src/tools/trigger-automation.ts
|
|
7605
|
-
import { z as
|
|
7606
|
-
var
|
|
7607
|
-
automationId:
|
|
7751
|
+
import { z as z83 } from "zod";
|
|
7752
|
+
var parameters21 = {
|
|
7753
|
+
automationId: z83.string().describe("The id of the automation, as returned by find-automations."),
|
|
7608
7754
|
workspaceId: workspaceIdParameter
|
|
7609
7755
|
};
|
|
7610
|
-
var
|
|
7611
|
-
automationId:
|
|
7612
|
-
name:
|
|
7613
|
-
accepted:
|
|
7756
|
+
var outputSchema19 = {
|
|
7757
|
+
automationId: z83.string(),
|
|
7758
|
+
name: z83.string(),
|
|
7759
|
+
accepted: z83.literal(true).describe("The backend accepted the run. It has not finished.")
|
|
7614
7760
|
};
|
|
7615
7761
|
var triggerAutomation = {
|
|
7616
7762
|
name: ToolNames.TRIGGER_AUTOMATION,
|
|
7617
7763
|
description: "Starts a run of a schedule-triggered automation now, without waiting for its next scheduled time, and returns as soon as the backend accepts it. The run happens in the background; find-runs shows the outcome. Runs even when the automation is disabled. Cannot start automations that run on events or API calls. Confirm intent with the user first.",
|
|
7618
|
-
parameters:
|
|
7619
|
-
outputSchema:
|
|
7764
|
+
parameters: parameters21,
|
|
7765
|
+
outputSchema: outputSchema19,
|
|
7620
7766
|
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false },
|
|
7621
7767
|
async execute({ automationId, workspaceId }, { api, signal }) {
|
|
7622
7768
|
const options = { signal };
|
|
@@ -7641,22 +7787,22 @@ var triggerAutomation = {
|
|
|
7641
7787
|
};
|
|
7642
7788
|
|
|
7643
7789
|
// src/tools/update-automation.ts
|
|
7644
|
-
import { z as
|
|
7645
|
-
var
|
|
7646
|
-
automationId:
|
|
7790
|
+
import { z as z84 } from "zod";
|
|
7791
|
+
var parameters22 = {
|
|
7792
|
+
automationId: z84.string().describe("The id of the automation, as returned by find-automations."),
|
|
7647
7793
|
workspaceId: workspaceIdParameter,
|
|
7648
|
-
name:
|
|
7649
|
-
description:
|
|
7650
|
-
enabled:
|
|
7794
|
+
name: z84.string().min(1).optional().describe("A new name. Omit to keep the current one."),
|
|
7795
|
+
description: z84.string().optional().describe("A new description. Omit to keep the current one."),
|
|
7796
|
+
enabled: z84.boolean().optional().describe(
|
|
7651
7797
|
"Turn the automation on or off. Enabling fails while disabledReason is set: the system stopped it and the cause must be fixed first."
|
|
7652
7798
|
)
|
|
7653
7799
|
};
|
|
7654
|
-
var
|
|
7800
|
+
var outputSchema20 = { automation: automationSummarySchema };
|
|
7655
7801
|
var updateAutomation = {
|
|
7656
7802
|
name: ToolNames.UPDATE_AUTOMATION,
|
|
7657
7803
|
description: "Renames, describes, enables or disables an automation. Any one field can change alone; the others keep their current values. Takes effect immediately with no confirmation of its own, so confirm intent with the user first. Does not change what the automation does; that needs a conversation.",
|
|
7658
|
-
parameters:
|
|
7659
|
-
outputSchema:
|
|
7804
|
+
parameters: parameters22,
|
|
7805
|
+
outputSchema: outputSchema20,
|
|
7660
7806
|
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true },
|
|
7661
7807
|
async execute({ automationId, workspaceId, name, description, enabled }, context) {
|
|
7662
7808
|
const client = createClient(automationId, workspaceId, context);
|
|
@@ -7722,6 +7868,8 @@ var toolRegistry = {
|
|
|
7722
7868
|
// Mutation
|
|
7723
7869
|
updateAutomation,
|
|
7724
7870
|
setAutomationSchedule,
|
|
7871
|
+
setAutomationVisibility,
|
|
7872
|
+
moveAutomation,
|
|
7725
7873
|
triggerAutomation,
|
|
7726
7874
|
// Connection
|
|
7727
7875
|
connectService,
|
|
@@ -7744,8 +7892,12 @@ You have access to a user's Todoist Automations through the tools listed.
|
|
|
7744
7892
|
|
|
7745
7893
|
- Every reference is an opaque id taken from a find- or get- tool. There is no lookup by name and no URL parsing: list first, then act on the id. Connector ids are the one exception: they are stable slugs such as github or slack.
|
|
7746
7894
|
- An automation belongs either to the user's personal space or to one Todoist workspace, and the two are separate. Pass workspaceId to reach workspace automations; omit it for personal ones.
|
|
7747
|
-
- update-automation, set-automation-schedule, trigger-automation and disconnect-service act immediately: no preview, and no confirmation of their own. Read the target first (get-automation, or get-connector for a connection) so it is the right one, and confirm intent with the user before changing or running anything they did not explicitly ask for.
|
|
7895
|
+
- update-automation, set-automation-schedule, set-automation-visibility, move-automation, trigger-automation and disconnect-service act immediately: no preview, and no confirmation of their own. Read the target first (get-automation, or get-connector for a connection) so it is the right one, and confirm intent with the user before changing or running anything they did not explicitly ask for.
|
|
7748
7896
|
- trigger-automation returns before the run finishes; find-runs shows the outcome.
|
|
7897
|
+
- A workspace automation is either visible to the whole workspace or private to its creator; isOwner says whether the user created it. Another member's automation is read-only for the user, but trigger-automation still works on it and the run executes on its creator's connections; find-runs shows who started each run as triggeredBy.
|
|
7898
|
+
- A workspace admin can update-automation and set-automation-visibility on another member's team-visible automation, but cannot reschedule it, change what it does (that needs its creator's draft or conversation) or reach a private one. updatedBy on an automation tells the creator's own change from an admin's.
|
|
7899
|
+
- move-automation puts an automation the user created into a workspace, from the personal space or another workspace, and never back out. Connections stay personal in every space: a moved or shared automation keeps running on its creator's own connections.
|
|
7900
|
+
- Authoring happens in the space the conversation was started in: pass workspaceId to start-conversation to author a workspace automation, and continue-conversation follows it automatically.
|
|
7749
7901
|
- connect-service and repair-connection never wait. They return what the user must complete (an authorisation link, or instructions and a code): relay it verbatim, let the user finish, then call check-connection with the connectionId. Retrying reuses the pending setup rather than creating another connection.
|
|
7750
7902
|
- disconnect-service refuses when enabled automations depend on the connection and returns them; disable them first, or pass force only after the user has agreed.
|
|
7751
7903
|
- New automations are authored in a conversation with the Automations agent: start-conversation, then continue-conversation with the same conversationId. Each call runs one turn and blocks until it ends, which can take minutes. A turn ends in one of three outcomes: awaiting_input (reply with a message), action_required (resolve pendingAction: have the user choose or authorise the listed connections, or enable push notifications in a Todoist app, then continue-conversation with no message) or published (an automation exists; get-automation shows it). Say in the message whether the automation should be published or kept as a draft; the agent otherwise asks.
|
|
@@ -7777,4 +7929,4 @@ export {
|
|
|
7777
7929
|
DEFAULT_BASE_URL,
|
|
7778
7930
|
getMcpServer
|
|
7779
7931
|
};
|
|
7780
|
-
//# sourceMappingURL=chunk-
|
|
7932
|
+
//# sourceMappingURL=chunk-BU6WJ7QM.js.map
|