mcp-sunsama 0.8.0 → 0.9.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/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # mcp-sunsama
2
2
 
3
+ ## 0.9.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 953ecb7: Add update-task-notes tool for updating task notes content
8
+
9
+ - New `update-task-notes` tool supports updating task notes with HTML or Markdown content
10
+ - Accepts either `{html: string}` or `{markdown: string}` content format (mutually exclusive)
11
+ - Includes optional `limitResponsePayload` parameter for response optimization
12
+ - Integrates with Sunsama's collaborative editing system for proper synchronization
13
+ - Follows established patterns for tool implementation and error handling
14
+ - Updates API documentation, README, and CLAUDE.md with new tool information
15
+
3
16
  ## 0.8.0
4
17
 
5
18
  ### Minor Changes
package/CLAUDE.md CHANGED
@@ -127,7 +127,7 @@ Optional:
127
127
  ### Task Operations
128
128
  Full CRUD support:
129
129
  - **Read**: `get-tasks-by-day`, `get-tasks-backlog`, `get-archived-tasks`, `get-task-by-id`, `get-streams`
130
- - **Write**: `create-task`, `update-task-complete`, `update-task-planned-time`, `update-task-snooze-date`, `update-task-backlog`, `delete-task`
130
+ - **Write**: `create-task`, `update-task-complete`, `update-task-planned-time`, `update-task-notes`, `update-task-snooze-date`, `update-task-backlog`, `delete-task`
131
131
 
132
132
  Task read operations support response trimming. `get-tasks-by-day` includes completion filtering. `get-archived-tasks` includes enhanced pagination with hasMore flag for LLM decision-making.
133
133
 
package/README.md CHANGED
@@ -95,6 +95,7 @@ Add this configuration to your Claude Desktop MCP settings:
95
95
  - `get-task-by-id` - Get a specific task by its ID
96
96
  - `update-task-complete` - Mark tasks as complete
97
97
  - `update-task-planned-time` - Update the planned time (time estimate) for tasks
98
+ - `update-task-notes` - Update task notes content with HTML or Markdown
98
99
  - `update-task-snooze-date` - Reschedule tasks to different dates
99
100
  - `update-task-backlog` - Move tasks to the backlog
100
101
  - `delete-task` - Delete tasks permanently
package/bun.lock CHANGED
@@ -7,7 +7,7 @@
7
7
  "@types/papaparse": "^5.3.16",
8
8
  "fastmcp": "3.3.1",
9
9
  "papaparse": "^5.5.3",
10
- "sunsama-api": "0.7.0",
10
+ "sunsama-api": "0.8.0",
11
11
  "zod": "3.24.4",
12
12
  },
13
13
  "devDependencies": {
@@ -58,6 +58,8 @@
58
58
 
59
59
  "@manypkg/get-packages": ["@manypkg/get-packages@1.1.3", "", { "dependencies": { "@babel/runtime": "^7.5.5", "@changesets/types": "^4.0.1", "@manypkg/find-root": "^1.1.0", "fs-extra": "^8.1.0", "globby": "^11.0.0", "read-yaml-file": "^1.1.0" } }, "sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A=="],
60
60
 
61
+ "@mixmark-io/domino": ["@mixmark-io/domino@2.2.0", "", {}, "sha512-Y28PR25bHXUg88kCV7nivXrP2Nj2RueZ3/l/jdx6J9f8J4nsEGcgX0Qe6lt7Pa+J79+kPiJU3LguR6O/6zrLOw=="],
62
+
61
63
  "@modelcontextprotocol/sdk": ["@modelcontextprotocol/sdk@1.12.1", "", { "dependencies": { "ajv": "^6.12.6", "content-type": "^1.0.5", "cors": "^2.8.5", "cross-spawn": "^7.0.5", "eventsource": "^3.0.2", "express": "^5.0.1", "express-rate-limit": "^7.5.0", "pkce-challenge": "^5.0.0", "raw-body": "^3.0.0", "zod": "^3.23.8", "zod-to-json-schema": "^3.24.1" } }, "sha512-KG1CZhZfWg+u8pxeM/mByJDScJSrjjxLc8fwQqbsS8xCjBmQfMNEBTotYdNanKekepnfRI85GtgQlctLFpcYPw=="],
62
64
 
63
65
  "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="],
@@ -282,6 +284,8 @@
282
284
 
283
285
  "lodash.startcase": ["lodash.startcase@4.4.0", "", {}, "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg=="],
284
286
 
287
+ "marked": ["marked@14.1.4", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-vkVZ8ONmUdPnjCKc5uTRvmkRbx4EAi2OkTOXmfTDhZz3OFqMNBM1oTTWwTr4HY4uAEojhzPf+Fy8F1DWa3Sndg=="],
288
+
285
289
  "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="],
286
290
 
287
291
  "mcp-proxy": ["mcp-proxy@5.1.0", "", { "dependencies": { "@modelcontextprotocol/sdk": "^1.12.1", "eventsource": "^4.0.0", "yargs": "^18.0.0" }, "bin": { "mcp-proxy": "dist/bin/mcp-proxy.js" } }, "sha512-6pfAdXFOvfpqse9dMLuQo8WTSFdD0al8vhr0Nx5EWv+dR6aTAHphdQj9NUP2xej2bhaWzJ5p8BRwbvXufOjJHA=="],
@@ -426,7 +430,7 @@
426
430
 
427
431
  "strtok3": ["strtok3@10.3.1", "", { "dependencies": { "@tokenizer/token": "^0.3.0" } }, "sha512-3JWEZM6mfix/GCJBBUrkA8p2Id2pBkyTkVCJKto55w080QBKZ+8R171fGrbiSp+yMO/u6F8/yUh7K4V9K+YCnw=="],
428
432
 
429
- "sunsama-api": ["sunsama-api@0.7.0", "", { "dependencies": { "graphql": "^16.11.0", "graphql-tag": "^2.12.6", "tough-cookie": "^5.1.2", "tslib": "^2.8.1", "yjs": "^13.6.27", "zod": "^3.25.64" } }, "sha512-/wPvJrtE0rUftl7c+OuQdu27OYkTvd23jzcQoAUP2SilQ6QYnFeG/Fjdf6nfl/MFuz5B8mpviGJdSgqYjAkd0g=="],
433
+ "sunsama-api": ["sunsama-api@0.8.0", "", { "dependencies": { "graphql": "^16.11.0", "graphql-tag": "^2.12.6", "marked": "^14.1.3", "tough-cookie": "^5.1.2", "tslib": "^2.8.1", "turndown": "^7.2.0", "yjs": "^13.6.27", "zod": "^3.25.64" } }, "sha512-EiUqEc2OIDsmfCHQX54Pu+xZDfJBTMjHAcwhWqHVIWTp2emMyitUuSDvABEqupoXrzITZw+XW0lxNZUQaW4lqQ=="],
430
434
 
431
435
  "term-size": ["term-size@2.2.1", "", {}, "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg=="],
432
436
 
@@ -446,6 +450,8 @@
446
450
 
447
451
  "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
448
452
 
453
+ "turndown": ["turndown@7.2.0", "", { "dependencies": { "@mixmark-io/domino": "^2.2.0" } }, "sha512-eCZGBN4nNNqM9Owkv9HAtWRYfLA4h909E/WGAWWBpmB275ehNhZyk87/Tpvjbp0jjNl9XwCsbe6bm6CqFsgD+A=="],
454
+
449
455
  "type-is": ["type-is@2.0.1", "", { "dependencies": { "content-type": "^1.0.5", "media-typer": "^1.1.0", "mime-types": "^3.0.0" } }, "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw=="],
450
456
 
451
457
  "typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="],
package/dist/main.js CHANGED
@@ -3,7 +3,7 @@ import { FastMCP } from "fastmcp";
3
3
  import { httpStreamAuthenticator } from "./auth/http.js";
4
4
  import { initializeStdioAuth } from "./auth/stdio.js";
5
5
  import { getTransportConfig } from "./config/transport.js";
6
- import { createTaskSchema, deleteTaskSchema, getArchivedTasksSchema, getStreamsSchema, getTaskByIdSchema, getTasksBacklogSchema, getTasksByDaySchema, getUserSchema, updateTaskBacklogSchema, updateTaskCompleteSchema, updateTaskPlannedTimeSchema, updateTaskSnoozeDateSchema } from "./schemas.js";
6
+ import { createTaskSchema, deleteTaskSchema, getArchivedTasksSchema, getStreamsSchema, getTaskByIdSchema, getTasksBacklogSchema, getTasksByDaySchema, getUserSchema, updateTaskBacklogSchema, updateTaskCompleteSchema, updateTaskNotesSchema, updateTaskPlannedTimeSchema, updateTaskSnoozeDateSchema } from "./schemas.js";
7
7
  import { getSunsamaClient } from "./utils/client-resolver.js";
8
8
  import { filterTasksByCompletion } from "./utils/task-filters.js";
9
9
  import { trimTasksForResponse } from "./utils/task-trimmer.js";
@@ -16,7 +16,7 @@ if (transportConfig.transportType === "stdio") {
16
16
  }
17
17
  const server = new FastMCP({
18
18
  name: "Sunsama API Server",
19
- version: "0.8.0",
19
+ version: "0.9.0",
20
20
  instructions: `
21
21
  This MCP server provides access to the Sunsama API for task and project management.
22
22
 
@@ -24,7 +24,7 @@ Available tools:
24
24
  - Authentication: login, logout, check authentication status
25
25
  - User operations: get current user information
26
26
  - Task operations: get tasks by day, get backlog tasks, get archived tasks, get task by ID
27
- - Task mutations: create tasks, mark complete, delete tasks, reschedule tasks, update planned time
27
+ - Task mutations: create tasks, mark complete, delete tasks, reschedule tasks, update planned time, update task notes
28
28
  - Stream operations: get streams/channels for the user's group
29
29
 
30
30
  Authentication is required for all operations. You can either:
@@ -568,6 +568,57 @@ server.addTool({
568
568
  }
569
569
  }
570
570
  });
571
+ server.addTool({
572
+ name: "update-task-notes",
573
+ description: "Update the notes content for a task",
574
+ parameters: updateTaskNotesSchema,
575
+ execute: async (args, { session, log }) => {
576
+ try {
577
+ // Extract parameters
578
+ const { taskId, content, limitResponsePayload } = args;
579
+ log.info("Updating task notes", {
580
+ taskId: taskId,
581
+ contentType: 'html' in content ? 'html' : 'markdown',
582
+ contentLength: ('html' in content ? content.html : content.markdown).length,
583
+ limitResponsePayload: limitResponsePayload
584
+ });
585
+ // Get the appropriate client based on transport type
586
+ const sunsamaClient = getSunsamaClient(session);
587
+ // Build options object
588
+ const options = {};
589
+ if (limitResponsePayload !== undefined)
590
+ options.limitResponsePayload = limitResponsePayload;
591
+ // Call sunsamaClient.updateTaskNotes(taskId, content, options)
592
+ const result = await sunsamaClient.updateTaskNotes(taskId, content, options);
593
+ log.info("Successfully updated task notes", {
594
+ taskId: taskId,
595
+ success: result.success,
596
+ contentType: 'html' in content ? 'html' : 'markdown'
597
+ });
598
+ return {
599
+ content: [
600
+ {
601
+ type: "text",
602
+ text: JSON.stringify({
603
+ success: result.success,
604
+ taskId: taskId,
605
+ notesUpdated: true,
606
+ updatedFields: result.updatedFields
607
+ })
608
+ }
609
+ ]
610
+ };
611
+ }
612
+ catch (error) {
613
+ log.error("Failed to update task notes", {
614
+ taskId: args.taskId,
615
+ contentType: 'html' in args.content ? 'html' : 'markdown',
616
+ error: error instanceof Error ? error.message : 'Unknown error'
617
+ });
618
+ throw new Error(`Failed to update task notes: ${error instanceof Error ? error.message : 'Unknown error'}`);
619
+ }
620
+ }
621
+ });
571
622
  // Stream Operations
572
623
  server.addTool({
573
624
  name: "get-streams",
@@ -698,6 +749,15 @@ Uses HTTP Basic Auth headers (per-request authentication):
698
749
  - \`limitResponsePayload\` (optional): Whether to limit response size
699
750
  - Returns: JSON with update result
700
751
 
752
+ - **update-task-notes**: Update task notes content
753
+ - Parameters:
754
+ - \`taskId\` (required): The ID of the task to update notes for
755
+ - \`content\` (required): Task notes content in either HTML or Markdown format
756
+ - \`{html: string}\` OR \`{markdown: string}\` (mutually exclusive)
757
+ - \`limitResponsePayload\` (optional): Whether to limit response size (defaults to true)
758
+ - Returns: JSON with update result
759
+ - Note: Supports both HTML and Markdown content with automatic format conversion
760
+
701
761
  ### Stream Operations
702
762
  - **get-streams**: Get streams for the user's group
703
763
  - Parameters: none
package/dist/schemas.d.ts CHANGED
@@ -141,6 +141,39 @@ export declare const updateTaskPlannedTimeSchema: z.ZodObject<{
141
141
  timeEstimateMinutes: number;
142
142
  limitResponsePayload?: boolean | undefined;
143
143
  }>;
144
+ export declare const updateTaskNotesSchema: z.ZodObject<{
145
+ taskId: z.ZodString;
146
+ content: z.ZodUnion<[z.ZodObject<{
147
+ html: z.ZodString;
148
+ }, "strip", z.ZodTypeAny, {
149
+ html: string;
150
+ }, {
151
+ html: string;
152
+ }>, z.ZodObject<{
153
+ markdown: z.ZodString;
154
+ }, "strip", z.ZodTypeAny, {
155
+ markdown: string;
156
+ }, {
157
+ markdown: string;
158
+ }>]>;
159
+ limitResponsePayload: z.ZodOptional<z.ZodBoolean>;
160
+ }, "strip", z.ZodTypeAny, {
161
+ taskId: string;
162
+ content: {
163
+ html: string;
164
+ } | {
165
+ markdown: string;
166
+ };
167
+ limitResponsePayload?: boolean | undefined;
168
+ }, {
169
+ taskId: string;
170
+ content: {
171
+ html: string;
172
+ } | {
173
+ markdown: string;
174
+ };
175
+ limitResponsePayload?: boolean | undefined;
176
+ }>;
144
177
  /**
145
178
  * Response Type Schemas (for validation and documentation)
146
179
  */
@@ -575,6 +608,7 @@ export type UpdateTaskCompleteInput = z.infer<typeof updateTaskCompleteSchema>;
575
608
  export type DeleteTaskInput = z.infer<typeof deleteTaskSchema>;
576
609
  export type UpdateTaskSnoozeDateInput = z.infer<typeof updateTaskSnoozeDateSchema>;
577
610
  export type UpdateTaskPlannedTimeInput = z.infer<typeof updateTaskPlannedTimeSchema>;
611
+ export type UpdateTaskNotesInput = z.infer<typeof updateTaskNotesSchema>;
578
612
  export type User = z.infer<typeof userSchema>;
579
613
  export type Task = z.infer<typeof taskSchema>;
580
614
  export type Stream = z.infer<typeof streamSchema>;
@@ -1 +1 @@
1
- {"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"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"}
package/dist/schemas.js CHANGED
@@ -76,6 +76,19 @@ export const updateTaskPlannedTimeSchema = z.object({
76
76
  timeEstimateMinutes: z.number().int().min(0).describe("Time estimate in minutes (use 0 to clear the time estimate)"),
77
77
  limitResponsePayload: z.boolean().optional().describe("Whether to limit the response payload size"),
78
78
  });
79
+ // Update task notes parameters
80
+ export const updateTaskNotesSchema = z.object({
81
+ taskId: z.string().min(1, "Task ID is required").describe("The ID of the task to update notes for"),
82
+ content: z.union([
83
+ z.object({
84
+ html: z.string().describe("HTML content for the task notes")
85
+ }),
86
+ z.object({
87
+ markdown: z.string().describe("Markdown content for the task notes")
88
+ })
89
+ ]).describe("Task notes content in either HTML or Markdown format"),
90
+ limitResponsePayload: z.boolean().optional().describe("Whether to limit the response payload size (defaults to true)"),
91
+ });
79
92
  /**
80
93
  * Response Type Schemas (for validation and documentation)
81
94
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-sunsama",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "MCP server for Sunsama API integration",
5
5
  "type": "module",
6
6
  "private": false,
@@ -26,7 +26,7 @@
26
26
  "@types/papaparse": "^5.3.16",
27
27
  "fastmcp": "3.3.1",
28
28
  "papaparse": "^5.5.3",
29
- "sunsama-api": "0.7.0",
29
+ "sunsama-api": "0.8.0",
30
30
  "zod": "3.24.4"
31
31
  },
32
32
  "devDependencies": {
package/src/main.ts CHANGED
@@ -16,6 +16,7 @@ import {
16
16
  getUserSchema,
17
17
  updateTaskBacklogSchema,
18
18
  updateTaskCompleteSchema,
19
+ updateTaskNotesSchema,
19
20
  updateTaskPlannedTimeSchema,
20
21
  updateTaskSnoozeDateSchema
21
22
  } from "./schemas.js";
@@ -34,7 +35,7 @@ if (transportConfig.transportType === "stdio") {
34
35
 
35
36
  const server = new FastMCP({
36
37
  name: "Sunsama API Server",
37
- version: "0.8.0",
38
+ version: "0.9.0",
38
39
  instructions: `
39
40
  This MCP server provides access to the Sunsama API for task and project management.
40
41
 
@@ -42,7 +43,7 @@ Available tools:
42
43
  - Authentication: login, logout, check authentication status
43
44
  - User operations: get current user information
44
45
  - Task operations: get tasks by day, get backlog tasks, get archived tasks, get task by ID
45
- - Task mutations: create tasks, mark complete, delete tasks, reschedule tasks, update planned time
46
+ - Task mutations: create tasks, mark complete, delete tasks, reschedule tasks, update planned time, update task notes
46
47
  - Stream operations: get streams/channels for the user's group
47
48
 
48
49
  Authentication is required for all operations. You can either:
@@ -689,6 +690,70 @@ server.addTool({
689
690
  }
690
691
  });
691
692
 
693
+ server.addTool({
694
+ name: "update-task-notes",
695
+ description: "Update the notes content for a task",
696
+ parameters: updateTaskNotesSchema,
697
+ execute: async (args, {session, log}) => {
698
+ try {
699
+ // Extract parameters
700
+ const {taskId, content, limitResponsePayload} = args;
701
+
702
+ log.info("Updating task notes", {
703
+ taskId: taskId,
704
+ contentType: 'html' in content ? 'html' : 'markdown',
705
+ contentLength: ('html' in content ? content.html : content.markdown).length,
706
+ limitResponsePayload: limitResponsePayload
707
+ });
708
+
709
+ // Get the appropriate client based on transport type
710
+ const sunsamaClient = getSunsamaClient(session as SessionData | null);
711
+
712
+ // Build options object
713
+ const options: {
714
+ limitResponsePayload?: boolean;
715
+ } = {};
716
+ if (limitResponsePayload !== undefined) options.limitResponsePayload = limitResponsePayload;
717
+
718
+ // Call sunsamaClient.updateTaskNotes(taskId, content, options)
719
+ const result = await sunsamaClient.updateTaskNotes(
720
+ taskId,
721
+ content,
722
+ options
723
+ );
724
+
725
+ log.info("Successfully updated task notes", {
726
+ taskId: taskId,
727
+ success: result.success,
728
+ contentType: 'html' in content ? 'html' : 'markdown'
729
+ });
730
+
731
+ return {
732
+ content: [
733
+ {
734
+ type: "text",
735
+ text: JSON.stringify({
736
+ success: result.success,
737
+ taskId: taskId,
738
+ notesUpdated: true,
739
+ updatedFields: result.updatedFields
740
+ })
741
+ }
742
+ ]
743
+ };
744
+
745
+ } catch (error) {
746
+ log.error("Failed to update task notes", {
747
+ taskId: args.taskId,
748
+ contentType: 'html' in args.content ? 'html' : 'markdown',
749
+ error: error instanceof Error ? error.message : 'Unknown error'
750
+ });
751
+
752
+ throw new Error(`Failed to update task notes: ${error instanceof Error ? error.message : 'Unknown error'}`);
753
+ }
754
+ }
755
+ });
756
+
692
757
  // Stream Operations
693
758
  server.addTool({
694
759
  name: "get-streams",
@@ -825,6 +890,15 @@ Uses HTTP Basic Auth headers (per-request authentication):
825
890
  - \`limitResponsePayload\` (optional): Whether to limit response size
826
891
  - Returns: JSON with update result
827
892
 
893
+ - **update-task-notes**: Update task notes content
894
+ - Parameters:
895
+ - \`taskId\` (required): The ID of the task to update notes for
896
+ - \`content\` (required): Task notes content in either HTML or Markdown format
897
+ - \`{html: string}\` OR \`{markdown: string}\` (mutually exclusive)
898
+ - \`limitResponsePayload\` (optional): Whether to limit response size (defaults to true)
899
+ - Returns: JSON with update result
900
+ - Note: Supports both HTML and Markdown content with automatic format conversion
901
+
828
902
  ### Stream Operations
829
903
  - **get-streams**: Get streams for the user's group
830
904
  - Parameters: none
package/src/schemas.ts CHANGED
@@ -94,6 +94,20 @@ export const updateTaskPlannedTimeSchema = z.object({
94
94
  limitResponsePayload: z.boolean().optional().describe("Whether to limit the response payload size"),
95
95
  });
96
96
 
97
+ // Update task notes parameters
98
+ export const updateTaskNotesSchema = z.object({
99
+ taskId: z.string().min(1, "Task ID is required").describe("The ID of the task to update notes for"),
100
+ content: z.union([
101
+ z.object({
102
+ html: z.string().describe("HTML content for the task notes")
103
+ }),
104
+ z.object({
105
+ markdown: z.string().describe("Markdown content for the task notes")
106
+ })
107
+ ]).describe("Task notes content in either HTML or Markdown format"),
108
+ limitResponsePayload: z.boolean().optional().describe("Whether to limit the response payload size (defaults to true)"),
109
+ });
110
+
97
111
  /**
98
112
  * Response Type Schemas (for validation and documentation)
99
113
  */
@@ -196,6 +210,7 @@ export type UpdateTaskCompleteInput = z.infer<typeof updateTaskCompleteSchema>;
196
210
  export type DeleteTaskInput = z.infer<typeof deleteTaskSchema>;
197
211
  export type UpdateTaskSnoozeDateInput = z.infer<typeof updateTaskSnoozeDateSchema>;
198
212
  export type UpdateTaskPlannedTimeInput = z.infer<typeof updateTaskPlannedTimeSchema>;
213
+ export type UpdateTaskNotesInput = z.infer<typeof updateTaskNotesSchema>;
199
214
 
200
215
  export type User = z.infer<typeof userSchema>;
201
216
  export type Task = z.infer<typeof taskSchema>;