@fukuchang/taskchute-mcp 0.3.0 → 0.4.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.
Files changed (2) hide show
  1. package/dist/index.js +45 -9
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -218,14 +218,14 @@ async function deriveKEK(password, salt, params = DEFAULT_ARGON2ID_PARAMS) {
218
218
  }
219
219
 
220
220
  // ../crypto/src/wrap.ts
221
- async function unwrapMasterKey(wrapped, iv, kek) {
221
+ async function unwrapMasterKey(wrapped, iv, kek, options = {}) {
222
222
  return crypto.subtle.unwrapKey(
223
223
  "raw",
224
224
  wrapped,
225
225
  kek,
226
226
  { name: "AES-GCM", iv },
227
227
  { name: "AES-GCM", length: 256 },
228
- false,
228
+ options.extractable ?? false,
229
229
  ["encrypt", "decrypt"]
230
230
  );
231
231
  }
@@ -511,6 +511,7 @@ async function rowToContext(row, cryptoSession) {
511
511
  id: row.id,
512
512
  name,
513
513
  status: row.status,
514
+ notifyAtScheduledStart: row.notify_at_scheduled_start,
514
515
  createdAt: new Date(row.created_at),
515
516
  updatedAt: new Date(row.updated_at)
516
517
  };
@@ -524,6 +525,9 @@ function nonEncryptedFieldsToRow(input) {
524
525
  if ("icon" in input) row.icon = input.icon ?? null;
525
526
  if ("color" in input) row.color = input.color ?? null;
526
527
  if ("status" in input && input.status !== void 0) row.status = input.status;
528
+ if ("notifyAtScheduledStart" in input && input.notifyAtScheduledStart !== void 0) {
529
+ row.notify_at_scheduled_start = input.notifyAtScheduledStart;
530
+ }
527
531
  return row;
528
532
  }
529
533
  async function encryptContextFieldsInto(row, entityId, patch, cryptoSession) {
@@ -2210,6 +2214,14 @@ function pickPropagationTargets(routine, tasks, today) {
2210
2214
  );
2211
2215
  }
2212
2216
 
2217
+ // ../domain/src/context-task-inheritance.ts
2218
+ function applyContextNotificationInheritance(input, context) {
2219
+ if (context?.notifyAtScheduledStart !== true) return input;
2220
+ const current = input.notifyAtScheduledStart;
2221
+ if (current !== void 0) return input;
2222
+ return { ...input, notifyAtScheduledStart: true };
2223
+ }
2224
+
2213
2225
  // ../infra-supabase/src/audit-task-repository.ts
2214
2226
  var AuditingTaskRepository = class {
2215
2227
  // `erasableSyntaxOnly` 配下では parameter property が使えないので、明示的に
@@ -2499,8 +2511,9 @@ async function addTaskHandler(ctx, input) {
2499
2511
  const project = await ctx.repos.project.findById(input.project_id);
2500
2512
  if (!project) throw new McpToolError(`Project not found: ${input.project_id}`);
2501
2513
  }
2514
+ let context = null;
2502
2515
  if (input.context_id) {
2503
- const context = await ctx.repos.context.findById(input.context_id);
2516
+ context = await ctx.repos.context.findById(input.context_id);
2504
2517
  if (!context) throw new McpToolError(`Context not found: ${input.context_id}`);
2505
2518
  }
2506
2519
  if (input.tag_ids && input.tag_ids.length > 0) {
@@ -2516,7 +2529,7 @@ async function addTaskHandler(ctx, input) {
2516
2529
  const estimatedSeconds = input.estimated_seconds ?? DEFAULT_ESTIMATED_SECONDS;
2517
2530
  const existing = await ctx.repos.task.findByDate(date);
2518
2531
  const orderIndex = computeNextOrderIndex(existing);
2519
- const task = await ctx.repos.task.create({
2532
+ const createInput = {
2520
2533
  date,
2521
2534
  title: input.title,
2522
2535
  description: input.description,
@@ -2530,7 +2543,10 @@ async function addTaskHandler(ctx, input) {
2530
2543
  scheduledStartTime: input.scheduled_start_time,
2531
2544
  notifyAtScheduledStart: input.notify_at_scheduled_start,
2532
2545
  isBackground: input.is_background
2533
- });
2546
+ };
2547
+ const task = await ctx.repos.task.create(
2548
+ applyContextNotificationInheritance(createInput, context)
2549
+ );
2534
2550
  return { task: taskSummaryFrom(task) };
2535
2551
  }
2536
2552
 
@@ -2540,6 +2556,7 @@ function contextSummaryFrom(context) {
2540
2556
  id: context.id,
2541
2557
  name: context.name,
2542
2558
  status: context.status,
2559
+ notify_at_scheduled_start: context.notifyAtScheduledStart ?? false,
2543
2560
  created_at: context.createdAt.toISOString(),
2544
2561
  updated_at: context.updatedAt.toISOString()
2545
2562
  };
@@ -2701,7 +2718,10 @@ var createContextInputSchema = z.object({
2701
2718
  name: z.string().min(1, "name must not be empty"),
2702
2719
  description: z.string().optional(),
2703
2720
  icon: z.string().optional().describe("\u7D75\u6587\u5B57\u307E\u305F\u306F\u30A2\u30A4\u30B3\u30F3\u540D (\u4F8B: \u{1F3E0} / mdi-home)"),
2704
- color: z.string().optional().describe("UI \u8272 (\u4F8B: #ff6b6b)")
2721
+ color: z.string().optional().describe("UI \u8272 (\u4F8B: #ff6b6b)"),
2722
+ notify_at_scheduled_start: z.boolean().optional().describe(
2723
+ "true \u306A\u3089\u3001\u3053\u306E\u30B3\u30F3\u30C6\u30AD\u30B9\u30C8\u3092\u4ED8\u3051\u305F\u65B0\u898F/\u66F4\u65B0\u30BF\u30B9\u30AF\u306E\u901A\u77E5\u3092 ON \u306B\u81EA\u52D5\u7D99\u627F\u3059\u308B"
2724
+ )
2705
2725
  });
2706
2726
  async function createContextHandler(ctx, input) {
2707
2727
  const createInput = {
@@ -2711,6 +2731,9 @@ async function createContextHandler(ctx, input) {
2711
2731
  if (input.description !== void 0) createInput.description = input.description;
2712
2732
  if (input.icon !== void 0) createInput.icon = input.icon;
2713
2733
  if (input.color !== void 0) createInput.color = input.color;
2734
+ if (input.notify_at_scheduled_start !== void 0) {
2735
+ createInput.notifyAtScheduledStart = input.notify_at_scheduled_start;
2736
+ }
2714
2737
  const context = await ctx.repos.context.create(createInput);
2715
2738
  return { context: contextSummaryFrom(context) };
2716
2739
  }
@@ -3192,7 +3215,10 @@ var updateContextInputSchema = z.object({
3192
3215
  description: z.union([z.string(), z.null()]).optional(),
3193
3216
  icon: z.union([z.string(), z.null()]).optional(),
3194
3217
  color: z.union([z.string(), z.null()]).optional(),
3195
- status: z.enum(["active", "archived"]).optional().describe("archived \u5316\u306F archive_context tool \u63A8\u5968")
3218
+ status: z.enum(["active", "archived"]).optional().describe("archived \u5316\u306F archive_context tool \u63A8\u5968"),
3219
+ notify_at_scheduled_start: z.boolean().optional().describe(
3220
+ "true \u306A\u3089\u3001\u3053\u306E\u30B3\u30F3\u30C6\u30AD\u30B9\u30C8\u3092\u4ED8\u3051\u305F\u65B0\u898F/\u66F4\u65B0\u30BF\u30B9\u30AF\u306E\u901A\u77E5\u3092 ON \u306B\u81EA\u52D5\u7D99\u627F\u3059\u308B"
3221
+ )
3196
3222
  });
3197
3223
  async function updateContextHandler(ctx, input) {
3198
3224
  const existing = await ctx.repos.context.findById(input.id);
@@ -3211,6 +3237,9 @@ async function updateContextHandler(ctx, input) {
3211
3237
  patch.color = input.color === null ? void 0 : input.color;
3212
3238
  }
3213
3239
  if (input.status !== void 0) patch.status = input.status;
3240
+ if (input.notify_at_scheduled_start !== void 0) {
3241
+ patch.notifyAtScheduledStart = input.notify_at_scheduled_start;
3242
+ }
3214
3243
  const updated = await ctx.repos.context.update(input.id, patch);
3215
3244
  return { context: contextSummaryFrom(updated) };
3216
3245
  }
@@ -3350,9 +3379,11 @@ async function updateRoutineHandler(ctx, input) {
3350
3379
  );
3351
3380
  }
3352
3381
  const taskPatch = buildRoutineTaskPatch(updated);
3382
+ const routineContext = updated.contextId ? await ctx.repos.context.findById(updated.contextId) : null;
3383
+ const propagatedPatch = applyContextNotificationInheritance(taskPatch, routineContext);
3353
3384
  await Promise.all(
3354
3385
  targets.map(
3355
- (task) => auditingTask.updateWithCause(task.id, taskPatch, "routine-propagation")
3386
+ (task) => auditingTask.updateWithCause(task.id, propagatedPatch, "routine-propagation")
3356
3387
  )
3357
3388
  );
3358
3389
  }
@@ -3446,6 +3477,11 @@ async function updateTaskHandler(ctx, input) {
3446
3477
  patch.notifyAtScheduledStart = input.notify_at_scheduled_start;
3447
3478
  }
3448
3479
  if (input.is_background !== void 0) patch.isBackground = input.is_background;
3480
+ const newContextId = patch.contextId;
3481
+ if (newContextId) {
3482
+ const newContext = await ctx.repos.context.findById(newContextId);
3483
+ Object.assign(patch, applyContextNotificationInheritance(patch, newContext));
3484
+ }
3449
3485
  const updated = await ctx.repos.task.update(input.id, patch);
3450
3486
  return { task: taskSummaryFrom(updated) };
3451
3487
  }
@@ -3900,7 +3936,7 @@ function createMcpServer(opts) {
3900
3936
 
3901
3937
  // src/index.ts
3902
3938
  async function main() {
3903
- const version = "0.3.0" ;
3939
+ const version = "0.4.0" ;
3904
3940
  const server = createMcpServer({ version });
3905
3941
  const transport = new StdioServerTransport();
3906
3942
  await server.connect(transport);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fukuchang/taskchute-mcp",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "TaskChute MCP server — Model Context Protocol 経由で E2EE 暗号化された TaskChute タスクを Claude / 各種 MCP クライアントから操作する",
5
5
  "license": "MIT",
6
6
  "author": "fukuchang",