mcp-sunsama 0.4.0 → 0.5.1

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.
@@ -1,4 +1,5 @@
1
1
  {
2
+ "includeCoAuthoredBy": false,
2
3
  "permissions": {
3
4
  "allow": [
4
5
  "mcp__context7__resolve-library-id",
@@ -17,7 +18,10 @@
17
18
  "Bash(npm ls:*)",
18
19
  "Bash(cat:*)",
19
20
  "Bash(grep:*)",
20
- "Bash(mkdir:*)"
21
+ "Bash(mkdir:*)",
22
+ "mcp__fetch__fetch",
23
+ "Bash(npm view:*)",
24
+ "Bash(npm info:*)"
21
25
  ],
22
26
  "deny": []
23
27
  },
package/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # mcp-sunsama
2
2
 
3
+ ## 0.5.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 005209d: Add prepublishOnly script to ensure build runs before publishing
8
+
9
+ ## 0.5.0
10
+
11
+ ### Minor Changes
12
+
13
+ - 8478b69: Add get-archived-tasks tool with enhanced pagination
14
+
15
+ - Implement get-archived-tasks tool to access archived task history
16
+ - Add smart pagination with limit+1 pattern to determine if more results exist
17
+ - Include pagination metadata (hasMore flag, nextOffset, count) for LLM context
18
+ - Default limit set to 100 for optimal performance
19
+ - Response format includes TSV data with pagination header
20
+ - Update documentation in README.md and CLAUDE.md
21
+
3
22
  ## 0.4.0
4
23
 
5
24
  ### Minor Changes
package/CLAUDE.md CHANGED
@@ -52,6 +52,14 @@ Two-tier optimization for large datasets:
52
52
 
53
53
  Always apply filtering before trimming for efficiency.
54
54
 
55
+ ### Enhanced Pagination Pattern
56
+ The `get-archived-tasks` tool implements smart pagination:
57
+
58
+ - **Limit+1 Pattern**: Fetches `requestedLimit + 1` to determine if more results exist
59
+ - **Pagination Metadata**: Returns `hasMore` flag, `nextOffset`, and count information
60
+ - **LLM Context**: Provides clear guidance for AI assistants on whether to continue fetching
61
+ - **Response Format**: TSV data with pagination header for optimal processing
62
+
55
63
  ### Schema Architecture
56
64
  All tools use Zod schemas from `schemas.ts`:
57
65
  - Type-safe parameter validation
@@ -118,10 +126,10 @@ Optional:
118
126
 
119
127
  ### Task Operations
120
128
  Full CRUD support:
121
- - **Read**: `get-tasks-by-day`, `get-tasks-backlog`, `get-streams`
129
+ - **Read**: `get-tasks-by-day`, `get-tasks-backlog`, `get-archived-tasks`, `get-streams`
122
130
  - **Write**: `create-task`, `update-task-complete`, `delete-task`
123
131
 
124
- All task operations support completion filtering and response trimming.
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.
125
133
 
126
134
  ### Testing Tools
127
135
  Use MCP Inspector for debugging: `bun run inspect`
@@ -140,6 +148,4 @@ When updating the version:
140
148
 
141
149
  **IMPORTANT**: Never commit the `dev/` directory or any of its files to git. This directory contains development data including sample API responses and testing data that should remain local only.
142
150
 
143
- **IMPORTANT**: Never include "Claude" in git commit messages. Keep commit messages professional and focused on the actual changes made.
144
-
145
151
  **Branch Naming Convention**: Use the format `{type}/{short-name}` where `{type}` follows conventional commit naming convention (feat, fix, chore, refactor, docs, style, test, ci, etc.).
package/Dockerfile ADDED
@@ -0,0 +1,35 @@
1
+ # ----- Build Stage -----
2
+ FROM oven/bun:1-alpine AS builder
3
+ WORKDIR /app
4
+
5
+ # Copy package and configuration files
6
+ COPY package.json bun.lock* tsconfig.json ./
7
+
8
+ # Copy source code
9
+ COPY src ./src
10
+
11
+ # Install dependencies and build
12
+ RUN bun install && bun run build
13
+
14
+ # ----- Production Stage -----
15
+ FROM oven/bun:1-alpine
16
+ WORKDIR /app
17
+
18
+ # Copy built artifacts
19
+ COPY --from=builder /app/dist ./dist
20
+
21
+ # Copy package.json for production install
22
+ COPY package.json ./
23
+
24
+ # Install only production dependencies
25
+ RUN bun install --production --frozen-lockfile
26
+
27
+ # Set environment defaults for containerized deployment
28
+ ENV TRANSPORT_TYPE=httpStream
29
+ ENV PORT=3000
30
+
31
+ # Expose HTTP port
32
+ EXPOSE 3000
33
+
34
+ # Start the application
35
+ CMD ["bun", "dist/main.js"]
package/README.md CHANGED
@@ -6,7 +6,7 @@ A Model Context Protocol (MCP) server that provides comprehensive task managemen
6
6
 
7
7
  ### Task Management
8
8
  - **Create Tasks** - Create new tasks with notes, time estimates, due dates, and stream assignments
9
- - **Read Tasks** - Get tasks by day with completion filtering, access backlog tasks
9
+ - **Read Tasks** - Get tasks by day with completion filtering, access backlog tasks, retrieve archived task history
10
10
  - **Update Tasks** - Mark tasks as complete with custom timestamps, reschedule tasks or move to backlog
11
11
  - **Delete Tasks** - Permanently remove tasks from your workspace
12
12
 
@@ -91,6 +91,7 @@ Add this configuration to your Claude Desktop MCP settings:
91
91
  - `create-task` - Create new tasks with optional properties
92
92
  - `get-tasks-by-day` - Get tasks for a specific day with completion filtering
93
93
  - `get-tasks-backlog` - Get backlog tasks
94
+ - `get-archived-tasks` - Get archived tasks with pagination (includes hasMore flag for LLM context)
94
95
  - `update-task-complete` - Mark tasks as complete
95
96
  - `update-task-snooze-date` - Reschedule tasks to different dates or move to backlog
96
97
  - `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.3.1",
10
+ "sunsama-api": "0.6.1",
11
11
  "zod": "3.24.4",
12
12
  },
13
13
  "devDependencies": {
@@ -268,12 +268,16 @@
268
268
 
269
269
  "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
270
270
 
271
+ "isomorphic.js": ["isomorphic.js@0.2.5", "", {}, "sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw=="],
272
+
271
273
  "js-yaml": ["js-yaml@3.14.1", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g=="],
272
274
 
273
275
  "json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="],
274
276
 
275
277
  "jsonfile": ["jsonfile@4.0.0", "", { "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg=="],
276
278
 
279
+ "lib0": ["lib0@0.2.108", "", { "dependencies": { "isomorphic.js": "^0.2.4" }, "bin": { "0gentesthtml": "bin/gentesthtml.js", "0serve": "bin/0serve.js", "0ecdsa-generate-keypair": "bin/0ecdsa-generate-keypair.js" } }, "sha512-+3eK/B0SqYoZiQu9fNk4VEc6EX8cb0Li96tPGKgugzoGj/OdRdREtuTLvUW+mtinoB2mFiJjSqOJBIaMkAGhxQ=="],
280
+
277
281
  "locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="],
278
282
 
279
283
  "lodash.startcase": ["lodash.startcase@4.4.0", "", {}, "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg=="],
@@ -422,7 +426,7 @@
422
426
 
423
427
  "strtok3": ["strtok3@10.3.1", "", { "dependencies": { "@tokenizer/token": "^0.3.0" } }, "sha512-3JWEZM6mfix/GCJBBUrkA8p2Id2pBkyTkVCJKto55w080QBKZ+8R171fGrbiSp+yMO/u6F8/yUh7K4V9K+YCnw=="],
424
428
 
425
- "sunsama-api": ["sunsama-api@0.3.1", "", { "dependencies": { "graphql": "^16.11.0", "graphql-tag": "^2.12.6", "tough-cookie": "^5.1.2", "tslib": "^2.8.1", "zod": "^3.25.64" } }, "sha512-X0as5S6Wf3Pr9u1Ze/5Z9YzHfMNBxTqloMr9FmwOfPr3XXiDjstuGHAB6quRf0VhcUK56pOBm8y8rs3o3diOHA=="],
429
+ "sunsama-api": ["sunsama-api@0.6.1", "", { "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-4GhOdrAMo99JIXv9GZg7+NQJu1uPRgGbmnKFWTCNzXYiSVicNPNv27vgqHa3kJtPo19x8sBf4gOYZYlw6b1Wgw=="],
426
430
 
427
431
  "term-size": ["term-size@2.2.1", "", {}, "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg=="],
428
432
 
@@ -478,6 +482,8 @@
478
482
 
479
483
  "yargs-parser": ["yargs-parser@22.0.0", "", {}, "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw=="],
480
484
 
485
+ "yjs": ["yjs@13.6.27", "", { "dependencies": { "lib0": "^0.2.99" } }, "sha512-OIDwaflOaq4wC6YlPBy2L6ceKeKuF7DeTxx+jPzv1FHn9tCZ0ZwSRnUBxD05E3yed46fv/FWJbvR+Ud7x0L7zw=="],
486
+
481
487
  "yoctocolors": ["yoctocolors@2.1.1", "", {}, "sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ=="],
482
488
 
483
489
  "zod": ["zod@3.24.4", "", {}, "sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg=="],
@@ -3,13 +3,15 @@
3
3
  * Supports both stdio and httpStream transports based on environment variables
4
4
  */
5
5
  export type TransportType = "stdio" | "httpStream";
6
- export interface TransportConfig {
7
- transportType: TransportType;
8
- httpStream?: {
6
+ export type TransportConfig = {
7
+ transportType: "stdio";
8
+ } | {
9
+ transportType: "httpStream";
10
+ httpStream: {
9
11
  port: number;
10
- endpoint: string;
12
+ endpoint: `/${string}`;
11
13
  };
12
- }
14
+ };
13
15
  /**
14
16
  * Gets the transport configuration based on environment variables
15
17
  *
@@ -1 +1 @@
1
- {"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/config/transport.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,YAAY,CAAC;AAEnD,MAAM,WAAW,eAAe;IAC9B,aAAa,EAAE,aAAa,CAAC;IAC7B,UAAU,CAAC,EAAE;QACX,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;CACH;AAcD;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,IAAI,eAAe,CA0BpD;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,OAAO,CAE/C;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAE1C"}
1
+ {"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/config/transport.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,YAAY,CAAC;AAEnD,MAAM,MAAM,eAAe,GACvB;IACF,aAAa,EAAE,OAAO,CAAC;CACxB,GACG;IACF,aAAa,EAAE,YAAY,CAAC;IAC5B,UAAU,EAAE;QACV,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,IAAI,MAAM,EAAE,CAAC;KACxB,CAAC;CACH,CAAC;AAgBF;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,IAAI,eAAe,CA0BpD;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,OAAO,CAE/C;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAE1C"}
@@ -12,7 +12,9 @@ const TransportEnvSchema = z.object({
12
12
  .transform(val => parseInt(val, 10))
13
13
  .pipe(z.number().min(1).max(65535))
14
14
  .optional(),
15
- HTTP_ENDPOINT: z.string().default("/mcp")
15
+ HTTP_ENDPOINT: z.string().refine(val => val.startsWith("/"), {
16
+ message: "HTTP_ENDPOINT must start with '/'"
17
+ }).transform(val => val).default("/mcp")
16
18
  });
17
19
  /**
18
20
  * Gets the transport configuration based on environment variables
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, getStreamsSchema, getTasksBacklogSchema, getTasksByDaySchema, getUserSchema, updateTaskCompleteSchema, updateTaskSnoozeDateSchema } from "./schemas.js";
6
+ import { createTaskSchema, deleteTaskSchema, getArchivedTasksSchema, getStreamsSchema, getTasksBacklogSchema, getTasksByDaySchema, getUserSchema, updateTaskCompleteSchema, 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,14 +16,14 @@ if (transportConfig.transportType === "stdio") {
16
16
  }
17
17
  const server = new FastMCP({
18
18
  name: "Sunsama API Server",
19
- version: "0.2.2",
19
+ version: "0.5.1",
20
20
  instructions: `
21
21
  This MCP server provides access to the Sunsama API for task and project management.
22
22
 
23
23
  Available tools:
24
24
  - Authentication: login, logout, check authentication status
25
25
  - User operations: get current user information
26
- - Task operations: get tasks by day, get backlog tasks
26
+ - Task operations: get tasks by day, get backlog tasks, get archived tasks
27
27
  - Stream operations: get streams/channels for the user's group
28
28
 
29
29
  Authentication is required for all operations. You can either:
@@ -149,6 +149,67 @@ server.addTool({
149
149
  }
150
150
  }
151
151
  });
152
+ server.addTool({
153
+ name: "get-archived-tasks",
154
+ description: "Get archived tasks with optional pagination",
155
+ parameters: getArchivedTasksSchema,
156
+ execute: async (args, { session, log }) => {
157
+ try {
158
+ // Extract and set defaults for parameters
159
+ const offset = args.offset || 0;
160
+ const requestedLimit = args.limit || 100;
161
+ // Fetch limit + 1 to determine if there are more results
162
+ const fetchLimit = requestedLimit + 1;
163
+ log.info("Getting archived tasks", {
164
+ offset,
165
+ requestedLimit,
166
+ fetchLimit
167
+ });
168
+ // Get the appropriate client based on transport type
169
+ const sunsamaClient = getSunsamaClient(session);
170
+ // Get archived tasks (fetch limit + 1 to check for more)
171
+ const allTasks = await sunsamaClient.getArchivedTasks(offset, fetchLimit);
172
+ // Determine if there are more results and slice to requested limit
173
+ const hasMore = allTasks.length > requestedLimit;
174
+ const tasks = hasMore ? allTasks.slice(0, requestedLimit) : allTasks;
175
+ // Trim tasks to reduce response size while preserving essential data
176
+ const trimmedTasks = trimTasksForResponse(tasks);
177
+ // Create pagination metadata
178
+ const paginationInfo = {
179
+ offset,
180
+ limit: requestedLimit,
181
+ count: tasks.length,
182
+ hasMore,
183
+ nextOffset: hasMore ? offset + requestedLimit : null
184
+ };
185
+ log.info("Successfully retrieved archived tasks", {
186
+ totalReturned: tasks.length,
187
+ hasMore,
188
+ offset,
189
+ requestedLimit
190
+ });
191
+ // Create response with pagination metadata header and TSV data
192
+ const responseText = `# Pagination: offset=${paginationInfo.offset}, limit=${paginationInfo.limit}, count=${paginationInfo.count}, hasMore=${paginationInfo.hasMore}, nextOffset=${paginationInfo.nextOffset || 'null'}
193
+ ${toTsv(trimmedTasks)}`;
194
+ return {
195
+ content: [
196
+ {
197
+ type: "text",
198
+ text: responseText
199
+ }
200
+ ]
201
+ };
202
+ }
203
+ catch (error) {
204
+ log.error("Failed to get archived tasks", {
205
+ offset: args.offset,
206
+ limit: args.limit,
207
+ error: error instanceof Error ? error.message : 'Unknown error'
208
+ });
209
+ throw new Error(`Failed to get archived tasks: ${error instanceof Error ? error.message : 'Unknown error'}`);
210
+ }
211
+ }
212
+ });
152
213
  // Task Mutation Operations
153
214
  server.addTool({
154
215
  name: "create-task",
@@ -397,15 +458,32 @@ server.addResource({
397
458
  text: `# Sunsama MCP Server Documentation
398
459
 
399
460
  ## Overview
400
- This MCP server provides access to the Sunsama API for task and project management.
401
- Authentication is handled server-side using environment variables.
461
+ This MCP server provides comprehensive access to the Sunsama API for task and project management.
462
+ Supports dual transport modes with different authentication strategies.
463
+
464
+ ## Transport Modes
465
+
466
+ ### Stdio Transport (Default)
467
+ - Single global authentication using environment variables
468
+ - Session maintained for entire server lifetime
469
+ - Best for single-user local development
470
+
471
+ ### HTTP Stream Transport
472
+ - Per-request authentication via HTTP Basic Auth
473
+ - Session-isolated client instances
474
+ - Supports multiple concurrent users
402
475
 
403
476
  ## Authentication
404
- The server authenticates to Sunsama using environment variables:
477
+
478
+ ### Stdio Transport
479
+ Uses environment variables (authenticated once at startup):
405
480
  - \`SUNSAMA_EMAIL\`: Your Sunsama account email
406
481
  - \`SUNSAMA_PASSWORD\`: Your Sunsama account password
407
482
 
408
- Authentication happens automatically on server startup. No client-side authentication is required.
483
+ ### HTTP Stream Transport
484
+ Uses HTTP Basic Auth headers (per-request authentication):
485
+ - \`Authorization: Basic <base64(email:password)>\`
486
+ - Credentials provided in each HTTP request
409
487
 
410
488
  ## Available Tools
411
489
 
@@ -414,93 +492,85 @@ Authentication happens automatically on server startup. No client-side authentic
414
492
  - Parameters: none
415
493
  - Returns: User object with profile, timezone, and primary group details
416
494
 
417
- ### Task Operations
495
+ ### Task Management
418
496
  - **get-tasks-by-day**: Get tasks for a specific day with optional filtering
419
497
  - Parameters:
420
498
  - \`day\` (required): Date in YYYY-MM-DD format
421
499
  - \`timezone\` (optional): Timezone string (e.g., "America/New_York")
422
- - \`completionFilter\` (optional): Filter by completion status
423
- - \`"all"\` (default): Return all tasks
424
- - \`"incomplete"\`: Return only incomplete tasks
425
- - \`"completed"\`: Return only completed tasks
426
- - Returns: Array of filtered Task objects for the specified day
500
+ - \`completionFilter\` (optional): Filter by completion status ("all", "incomplete", "completed")
501
+ - Returns: TSV of filtered Task objects for the specified day
427
502
 
428
503
  - **get-tasks-backlog**: Get tasks from the backlog
429
504
  - Parameters: none
430
- - Returns: Array of Task objects from the backlog
505
+ - Returns: TSV of Task objects from the backlog
431
506
 
432
- ### Stream Operations
433
- - **get-streams**: Get streams for the user's group
434
- - Parameters: none
435
- - Returns: Array of Stream objects
436
- - Note: Streams are called "channels" in the Sunsama UI. If a user requests channels, use this tool.
507
+ - **get-archived-tasks**: Get archived tasks with optional pagination
508
+ - Parameters:
509
+ - \`offset\` (optional): Pagination offset (defaults to 0)
510
+ - \`limit\` (optional): Maximum number of tasks to return (defaults to 100, max: 1000)
511
+ - Returns: TSV of trimmed archived Task objects with pagination metadata header
512
+ - Pagination: Uses limit+1 pattern to determine if more results are available
437
513
 
438
- ## Data Types
514
+ - **create-task**: Create a new task with optional properties
515
+ - Parameters:
516
+ - \`text\` (required): Task title/description
517
+ - \`notes\` (optional): Additional task notes
518
+ - \`streamIds\` (optional): Array of stream IDs to associate with task
519
+ - \`timeEstimate\` (optional): Time estimate in minutes
520
+ - \`dueDate\` (optional): Due date string (ISO format)
521
+ - \`snoozeUntil\` (optional): Snooze until date string (ISO format)
522
+ - \`private\` (optional): Whether the task is private
523
+ - \`taskId\` (optional): Custom task ID
524
+ - Returns: JSON with task creation result
439
525
 
440
- ### User Object
441
- \`\`\`typescript
442
- {
443
- _id: string;
444
- email: string;
445
- profile: {
446
- _id: string;
447
- email: string;
448
- firstName: string;
449
- lastName: string;
450
- timezone: string;
451
- avatarUrl?: string;
452
- };
453
- primaryGroup?: {
454
- groupId: string;
455
- name: string;
456
- role?: string;
457
- };
458
- }
459
- \`\`\`
526
+ - **update-task-complete**: Mark a task as complete
527
+ - Parameters:
528
+ - \`taskId\` (required): The ID of the task to mark as complete
529
+ - \`completeOn\` (optional): Completion timestamp (ISO format)
530
+ - \`limitResponsePayload\` (optional): Whether to limit response size
531
+ - Returns: JSON with completion result
460
532
 
461
- ### Task Object
462
- \`\`\`typescript
463
- {
464
- _id: string;
465
- title: string;
466
- description?: string;
467
- status: string;
468
- createdAt: string;
469
- updatedAt: string;
470
- scheduledDate?: string;
471
- completedAt?: string;
472
- streamId?: string;
473
- userId: string;
474
- groupId: string;
475
- }
476
- \`\`\`
533
+ - **delete-task**: Delete a task permanently
534
+ - Parameters:
535
+ - \`taskId\` (required): The ID of the task to delete
536
+ - \`limitResponsePayload\` (optional): Whether to limit response size
537
+ - \`wasTaskMerged\` (optional): Whether the task was merged before deletion
538
+ - Returns: JSON with deletion result
477
539
 
478
- ### Stream Object
479
- Note: Streams are called "channels" in the Sunsama UI.
480
- \`\`\`typescript
481
- {
482
- _id: string;
483
- name: string;
484
- color?: string;
485
- groupId: string;
486
- isActive: boolean;
487
- createdAt: string;
488
- updatedAt: string;
489
- }
490
- \`\`\`
540
+ - **update-task-snooze-date**: Reschedule tasks or move to backlog
541
+ - Parameters:
542
+ - \`taskId\` (required): The ID of the task to reschedule
543
+ - \`newDay\` (required): Target date in YYYY-MM-DD format, or null for backlog
544
+ - \`timezone\` (optional): Timezone string
545
+ - \`limitResponsePayload\` (optional): Whether to limit response size
546
+ - Returns: JSON with update result
491
547
 
492
- ## Error Handling
493
- - All operations require valid Sunsama authentication
494
- - Invalid dates will return validation errors
495
- - Network errors are handled gracefully with descriptive messages
496
- - Server maintains session state across tool calls
548
+ ### Stream Operations
549
+ - **get-streams**: Get streams for the user's group
550
+ - Parameters: none
551
+ - Returns: TSV of Stream objects
552
+ - Note: Streams are called "channels" in the Sunsama UI
553
+
554
+ ## Response Optimization
555
+ - **Task Filtering**: Applied before processing for efficiency
556
+ - **Task Trimming**: Removes non-essential fields, reducing payload by 60-80%
557
+ - **TSV Format**: Used for arrays to optimize data processing
497
558
 
498
559
  ## Environment Setup
499
- Required environment variables:
500
- - \`API_KEY\`: MCP server authentication key
560
+
561
+ ### Required (Stdio Transport)
501
562
  - \`SUNSAMA_EMAIL\`: Sunsama account email
502
563
  - \`SUNSAMA_PASSWORD\`: Sunsama account password
503
- - \`PORT\`: Server port (default: 3000)
564
+
565
+ ### Optional Configuration
566
+ - \`TRANSPORT_TYPE\`: "stdio" (default) | "httpStream"
567
+ - \`PORT\`: Server port for HTTP transport (default: 3002)
568
+
569
+ ## Error Handling
570
+ - Comprehensive parameter validation using Zod schemas
571
+ - Graceful handling of network errors with descriptive messages
572
+ - Session-specific error isolation in HTTP transport mode
573
+ - Proper authentication error responses
504
574
  `.trim()
505
575
  };
506
576
  }
@@ -509,19 +579,12 @@ Required environment variables:
509
579
  if (transportConfig.transportType === "httpStream") {
510
580
  // Log startup information
511
581
  console.log(`HTTP Stream configuration: port=${transportConfig.httpStream?.port}, endpoint=${transportConfig.httpStream?.endpoint}`);
512
- server.start({
513
- transportType: "httpStream",
514
- httpStream: {
515
- port: transportConfig.httpStream.port
516
- }
517
- }).then(() => {
582
+ server.start(transportConfig).then(() => {
518
583
  console.log(`Sunsama MCP Server running on port ${transportConfig.httpStream.port}`);
519
584
  console.log(`HTTP endpoint: ${transportConfig.httpStream.endpoint}`);
520
585
  console.log("Authentication: HTTP Basic Auth with Sunsama credentials");
521
586
  });
522
587
  }
523
588
  else {
524
- server.start({
525
- transportType: "stdio"
526
- });
589
+ server.start(transportConfig);
527
590
  }
package/dist/schemas.d.ts CHANGED
@@ -17,6 +17,16 @@ export declare const getTasksByDaySchema: z.ZodObject<{
17
17
  completionFilter?: "all" | "incomplete" | "completed" | undefined;
18
18
  }>;
19
19
  export declare const getTasksBacklogSchema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
20
+ export declare const getArchivedTasksSchema: z.ZodObject<{
21
+ offset: z.ZodOptional<z.ZodNumber>;
22
+ limit: z.ZodOptional<z.ZodNumber>;
23
+ }, "strip", z.ZodTypeAny, {
24
+ offset?: number | undefined;
25
+ limit?: number | undefined;
26
+ }, {
27
+ offset?: number | undefined;
28
+ limit?: number | undefined;
29
+ }>;
20
30
  /**
21
31
  * User Operation Schemas
22
32
  */
@@ -523,6 +533,7 @@ export declare const errorResponseSchema: z.ZodObject<{
523
533
  export type CompletionFilter = z.infer<typeof completionFilterSchema>;
524
534
  export type GetTasksByDayInput = z.infer<typeof getTasksByDaySchema>;
525
535
  export type GetTasksBacklogInput = z.infer<typeof getTasksBacklogSchema>;
536
+ export type GetArchivedTasksInput = z.infer<typeof getArchivedTasksSchema>;
526
537
  export type GetUserInput = z.infer<typeof getUserSchema>;
527
538
  export type GetStreamsInput = z.infer<typeof getStreamsSchema>;
528
539
  export type CreateTaskInput = z.infer<typeof createTaskSchema>;
@@ -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
@@ -12,6 +12,11 @@ export const getTasksByDaySchema = z.object({
12
12
  });
13
13
  // Get tasks backlog parameters (no parameters needed)
14
14
  export const getTasksBacklogSchema = z.object({});
15
+ // Get archived tasks parameters
16
+ export const getArchivedTasksSchema = z.object({
17
+ offset: z.number().int().min(0).optional().describe("Pagination offset (defaults to 0)"),
18
+ limit: z.number().int().min(1).max(1000).optional().describe("Maximum number of tasks to return (defaults to 100)"),
19
+ });
15
20
  /**
16
21
  * User Operation Schemas
17
22
  */
@@ -1,4 +1,4 @@
1
- import type { Task } from "sunsama-api";
1
+ import type { Task, TaskIntegration } from "sunsama-api";
2
2
  /**
3
3
  * Trimmed task type containing only essential properties for API responses.
4
4
  * Reduces response size by 60-80% while preserving core task information.
@@ -9,7 +9,10 @@ import type { Task } from "sunsama-api";
9
9
  */
10
10
  export type TrimmedTask = Pick<Task, '_id' | 'text' | 'completed' | 'assigneeId' | 'createdAt' | 'lastModified' | 'objectiveId' | 'completeDate' | 'timeEstimate' | 'dueDate' | 'notes' | 'streamIds'> & {
11
11
  /** Integration service name (e.g., 'website', 'googleCalendar') or null */
12
- integration: string | null;
12
+ integration: {
13
+ service: TaskIntegration['service'];
14
+ url?: string;
15
+ } | null;
13
16
  /** Array of subtask titles only (simplified from full subtask objects) */
14
17
  subtasks: string[];
15
18
  };
@@ -1 +1 @@
1
- {"version":3,"file":"task-trimmer.d.ts","sourceRoot":"","sources":["../../src/utils/task-trimmer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAExC;;;;;;;GAOG;AACH,MAAM,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,EAC/B,KAAK,GACL,MAAM,GACN,WAAW,GACX,YAAY,GACZ,WAAW,GACX,cAAc,GACd,aAAa,GACb,cAAc,GACd,cAAc,GACd,SAAS,GACT,OAAO,GACP,WAAW,CACd,GAAG;IACF,2EAA2E;IAC3E,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,0EAA0E;IAC1E,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,IAAI,GAAG,WAAW,CAiB3D;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,WAAW,EAAE,CAEjE"}
1
+ {"version":3,"file":"task-trimmer.d.ts","sourceRoot":"","sources":["../../src/utils/task-trimmer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEzD;;;;;;;GAOG;AACH,MAAM,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,EAC/B,KAAK,GACL,MAAM,GACN,WAAW,GACX,YAAY,GACZ,WAAW,GACX,cAAc,GACd,aAAa,GACb,cAAc,GACd,cAAc,GACd,SAAS,GACT,OAAO,GACP,WAAW,CACd,GAAG;IACF,2EAA2E;IAC3E,WAAW,EAAE;QACX,OAAO,EAAE,eAAe,CAAC,SAAS,CAAC,CAAC;QACpC,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,GAAG,IAAI,CAAC;IACT,0EAA0E;IAC1E,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,IAAI,GAAG,WAAW,CA4B3D;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,WAAW,EAAE,CAEjE"}
@@ -22,6 +22,15 @@
22
22
  * @returns Trimmed task object with only essential properties
23
23
  */
24
24
  export function trimTaskForResponse(task) {
25
+ let integration = null;
26
+ // Extract minimal integration data: service type and URL if available
27
+ // Integration identifiers vary by service - some have URLs (websites), others have different properties
28
+ if (task.integration) {
29
+ integration = { service: task.integration.service };
30
+ if ("url" in task.integration.identifier) {
31
+ integration.url = task.integration.identifier.url;
32
+ }
33
+ }
25
34
  return {
26
35
  _id: task._id,
27
36
  assigneeId: task.assigneeId,
@@ -29,7 +38,7 @@ export function trimTaskForResponse(task) {
29
38
  completed: task.completed,
30
39
  createdAt: task.createdAt,
31
40
  dueDate: task.dueDate,
32
- integration: task.integration?.service || null,
41
+ integration: integration,
33
42
  lastModified: task.lastModified,
34
43
  notes: task.notes,
35
44
  objectiveId: task.objectiveId,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-sunsama",
3
- "version": "0.4.0",
3
+ "version": "0.5.1",
4
4
  "description": "MCP server for Sunsama API integration",
5
5
  "type": "module",
6
6
  "private": false,
@@ -19,13 +19,14 @@
19
19
  "inspect": "npx @modelcontextprotocol/inspector --config ./mcp-inspector.json --server sunsama",
20
20
  "changeset": "changeset",
21
21
  "version": "changeset version",
22
- "release": "bun run build && changeset publish"
22
+ "release": "bun run build && changeset publish",
23
+ "prepublishOnly": "bun run build"
23
24
  },
24
25
  "dependencies": {
25
26
  "@types/papaparse": "^5.3.16",
26
27
  "fastmcp": "3.3.1",
27
28
  "papaparse": "^5.5.3",
28
- "sunsama-api": "0.3.1",
29
+ "sunsama-api": "0.6.1",
29
30
  "zod": "3.24.4"
30
31
  },
31
32
  "devDependencies": {