mcp-sunsama 0.17.0 → 0.18.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 (58) hide show
  1. package/.claude/commands/upgrade-sunsama-api.md +70 -0
  2. package/CHANGELOG.md +20 -0
  3. package/CLAUDE.md +1 -0
  4. package/__tests__/unit/tools/api-coverage.test.ts +128 -0
  5. package/bun.lock +2 -2
  6. package/dist/auth/http.d.ts.map +1 -1
  7. package/dist/auth/http.js +13 -6
  8. package/dist/auth/retry.d.ts +8 -0
  9. package/dist/auth/retry.d.ts.map +1 -0
  10. package/dist/auth/retry.js +25 -0
  11. package/dist/auth/stdio.d.ts.map +1 -1
  12. package/dist/auth/stdio.js +2 -1
  13. package/dist/auth/types.d.ts +7 -0
  14. package/dist/auth/types.d.ts.map +1 -1
  15. package/dist/auth/types.js +13 -0
  16. package/dist/constants.d.ts +1 -1
  17. package/dist/constants.js +1 -1
  18. package/dist/main.js +12 -18
  19. package/dist/schemas.d.ts +86 -0
  20. package/dist/schemas.d.ts.map +1 -1
  21. package/dist/schemas.js +36 -0
  22. package/dist/tools/calendar-tools.d.ts +4 -0
  23. package/dist/tools/calendar-tools.d.ts.map +1 -0
  24. package/dist/tools/calendar-tools.js +55 -0
  25. package/dist/tools/index.d.ts +2 -6
  26. package/dist/tools/index.d.ts.map +1 -1
  27. package/dist/tools/index.js +3 -0
  28. package/dist/tools/shared.d.ts +46 -36
  29. package/dist/tools/shared.d.ts.map +1 -1
  30. package/dist/tools/shared.js +16 -22
  31. package/dist/tools/stream-tools.d.ts +2 -12
  32. package/dist/tools/stream-tools.d.ts.map +1 -1
  33. package/dist/tools/task-tools.d.ts +22 -120
  34. package/dist/tools/task-tools.d.ts.map +1 -1
  35. package/dist/tools/task-tools.js +39 -1
  36. package/dist/tools/user-tools.d.ts +2 -12
  37. package/dist/tools/user-tools.d.ts.map +1 -1
  38. package/dist/transports/http.d.ts.map +1 -1
  39. package/dist/transports/http.js +21 -8
  40. package/dist/utils/client-resolver.d.ts +1 -1
  41. package/dist/utils/client-resolver.d.ts.map +1 -1
  42. package/dist/utils/client-resolver.js +15 -4
  43. package/dist/utils/task-trimmer.js +1 -1
  44. package/package.json +2 -2
  45. package/src/auth/http.ts +12 -6
  46. package/src/auth/retry.ts +35 -0
  47. package/src/auth/stdio.ts +2 -1
  48. package/src/auth/types.ts +14 -0
  49. package/src/constants.ts +1 -1
  50. package/src/main.ts +12 -18
  51. package/src/schemas.ts +85 -0
  52. package/src/tools/calendar-tools.ts +91 -0
  53. package/src/tools/index.ts +3 -0
  54. package/src/tools/shared.ts +63 -37
  55. package/src/tools/task-tools.ts +58 -0
  56. package/src/transports/http.ts +20 -8
  57. package/src/utils/client-resolver.ts +22 -6
  58. package/src/utils/task-trimmer.ts +1 -1
@@ -0,0 +1,70 @@
1
+ ---
2
+ description: Upgrade sunsama-api and add missing MCP tools
3
+ model: claude-opus-4-6
4
+ allowed-tools: Bash(bun:*), Bash(npm:*), Bash(cat:*), Bash(ls:*), Read, Write, Edit, Glob, Grep
5
+ ---
6
+
7
+ Upgrade the sunsama-api dependency to the latest version and ensure all new endpoints are wrapped as MCP tools.
8
+
9
+ ## Steps
10
+
11
+ 1. **Check current vs latest version**:
12
+ ```bash
13
+ cat package.json | grep sunsama-api
14
+ npm view sunsama-api version
15
+ ```
16
+ - If already on latest, inform user and stop
17
+
18
+ 2. **Upgrade the dependency**:
19
+ ```bash
20
+ bun add sunsama-api@latest
21
+ ```
22
+
23
+ 3. **Verify build passes**:
24
+ ```bash
25
+ bun run typecheck
26
+ bun test
27
+ ```
28
+ - If either fails, stop and report the issue
29
+
30
+ 4. **Analyze new API methods**:
31
+ - Read `node_modules/sunsama-api/dist/types/client/index.d.ts` to find the method class hierarchy
32
+ - Read each method class file to enumerate all public methods on `SunsamaClient`
33
+ - Compare against existing tools in `src/tools/` to find unwrapped methods
34
+ - Report: "Found X new methods not wrapped as MCP tools: [list]"
35
+
36
+ 5. **For each unwrapped method**:
37
+ - Read the method signature and JSDoc from the sunsama-api type definitions
38
+ - Read the corresponding types from `node_modules/sunsama-api/dist/types/types/api.d.ts`
39
+ - Add the appropriate Zod schema to `src/schemas.ts` following existing patterns
40
+ - Add the tool implementation to the appropriate file in `src/tools/`:
41
+ - User operations → `user-tools.ts`
42
+ - Task operations → `task-tools.ts`
43
+ - Stream operations → `stream-tools.ts`
44
+ - Calendar operations → `calendar-tools.ts`
45
+ - Update `src/tools/index.ts` if a new tools file was created
46
+
47
+ 6. **Verify new tools work**:
48
+ ```bash
49
+ bun run typecheck
50
+ bun test
51
+ ```
52
+
53
+ 7. **Create changeset**:
54
+ - If only dependency bump (no new tools): patch changeset
55
+ - If new tools added: minor changeset
56
+ - Write changeset to `.changeset/` with descriptive summary
57
+
58
+ 8. **Report summary**:
59
+ - Previous version → new version
60
+ - New methods found
61
+ - Tools added (if any)
62
+ - Changeset created
63
+
64
+ ## Notes
65
+
66
+ - Follow existing patterns in `src/tools/` for tool structure
67
+ - Use `withTransportClient` wrapper for all tools
68
+ - Prefer `formatJsonResponse` for single objects, `formatTsvResponse` for arrays
69
+ - Don't use `as` type assertions — if needed, request schema exports from sunsama-api
70
+ - Run typecheck after each file modification to catch errors early
package/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # mcp-sunsama
2
2
 
3
+ ## 0.18.0
4
+
5
+ ### Minor Changes
6
+
7
+ - f806778: Add three new tools for sunsama-api 0.14.0 endpoints:
8
+
9
+ - `reorder-task` — move a task to a specific 0-based position within a day
10
+ - `create-calendar-event` — create a new calendar event (with optional stream links, visibility, and task seed)
11
+ - `update-calendar-event` — update an existing calendar event (requires full CalendarEventUpdateData)
12
+
13
+ - f806778: Add `update-task-uncomplete` tool to mark a completed task as incomplete, wrapping the previously missing `SunsamaClient.updateTaskUncomplete()` method.
14
+
15
+ ### Patch Changes
16
+
17
+ - 846299b: Fix HTTP transport returning 401 for all errors instead of only authentication failures. Non-auth errors (transport failures, unexpected exceptions) now correctly return 500.
18
+ - c1badc0: Fix HTTP transport tools always falling through to stdio client. The MCP SDK provides `sessionId` as a string on the `extra` object, not a nested `session` object. `client-resolver` now checks `extra.sessionId` to look up the per-request authenticated client in `SessionManager`.
19
+ - d3f81d7: Add retry with exponential backoff for 429 rate limit errors during login. Both stdio startup auth and HTTP per-request auth now retry up to 3 times (delays: 1s, 5s, 15s) when `SunsamaAuthError` contains "429". Non-429 errors are rethrown immediately.
20
+ - 3f0070a: Eliminate any types in shared tool infrastructure. ToolConfig is now generic over the Zod schema so tool execute functions receive properly typed args. ToolContext.client is typed as SunsamaClient and session as unknown, removing the catch-all index signature.
21
+ - af74a9d: Update sunsama-api dependency to 0.14.0 (bug fix release — no new endpoints).
22
+
3
23
  ## 0.17.0
4
24
 
5
25
  ### Minor Changes
package/CLAUDE.md CHANGED
@@ -233,6 +233,7 @@ __tests__/
233
233
  - **Parameter Destructuring**: Function signatures directly destructure typed parameters
234
234
  - **Zod Schema Integration**: Full TypeScript inference from Zod schemas
235
235
  - **Eliminated `any` Types**: All parameters properly typed with generated types
236
+ - **Avoid Type Assertions**: Don't use `as` casts if possible. Never use `as unknown as X` — this bypasses all type checking. If you reach for these, stop and find a type-safe alternative (generics, type guards, schema validation, etc.)
236
237
 
237
238
  ## Testing Architecture
238
239
 
@@ -0,0 +1,128 @@
1
+ import { describe, test, expect } from "bun:test";
2
+ import { readdir, readFile } from "fs/promises";
3
+ import { join } from "path";
4
+
5
+ /**
6
+ * Extracts all public instance method names from sunsama-api client .d.ts files.
7
+ * Scans both base.d.ts and the methods/ subdirectory.
8
+ * Skips private, protected, static, and abstract members.
9
+ */
10
+ async function getSunsamaClientMethods(): Promise<Set<string>> {
11
+ const clientDir = join(
12
+ import.meta.dir,
13
+ "../../../node_modules/sunsama-api/dist/types/client",
14
+ );
15
+
16
+ const methodsDir = join(clientDir, "methods");
17
+
18
+ const methodFiles = (await readdir(methodsDir))
19
+ .filter((f) => f.endsWith(".d.ts"))
20
+ .map((f) => join(methodsDir, f));
21
+
22
+ const allFiles = [join(clientDir, "base.d.ts"), ...methodFiles];
23
+
24
+ const methods = new Set<string>();
25
+
26
+ for (const file of allFiles) {
27
+ const content = await readFile(file, "utf-8");
28
+ const lines = content.split("\n");
29
+
30
+ for (const line of lines) {
31
+ // Skip comment lines (JSDoc, inline comments)
32
+ const trimmed = line.trim();
33
+ if (trimmed.startsWith("*") || trimmed.startsWith("//")) continue;
34
+
35
+ // Skip private, protected, static, abstract, and constructor declarations
36
+ if (
37
+ trimmed.startsWith("private ") ||
38
+ trimmed.startsWith("protected ") ||
39
+ trimmed.startsWith("static ") ||
40
+ trimmed.startsWith("abstract ") ||
41
+ trimmed.startsWith("constructor")
42
+ ) continue;
43
+
44
+ // Match a public instance method: 4 spaces indent + camelCase name + (
45
+ const match = line.match(/^ ([a-z][a-zA-Z]+)\(/);
46
+ if (match) {
47
+ methods.add(match[1]);
48
+ }
49
+ }
50
+ }
51
+
52
+ return methods;
53
+ }
54
+
55
+ /**
56
+ * Extracts all SunsamaClient methods called in the MCP tool implementations
57
+ * by scanning for `context.client.<methodName>` patterns.
58
+ */
59
+ async function getWrappedMethods(): Promise<Set<string>> {
60
+ const toolsDir = join(import.meta.dir, "../../../src/tools");
61
+
62
+ const files = (await readdir(toolsDir)).filter(
63
+ (f) => f.endsWith(".ts") && f !== "shared.ts" && f !== "index.ts",
64
+ );
65
+
66
+ const methods = new Set<string>();
67
+ const callPattern = /context\.client\.([a-zA-Z]+)\(/g;
68
+
69
+ for (const file of files) {
70
+ const content = await readFile(join(toolsDir, file), "utf-8");
71
+ let match;
72
+ while ((match = callPattern.exec(content)) !== null) {
73
+ methods.add(match[1]);
74
+ }
75
+ }
76
+
77
+ return methods;
78
+ }
79
+
80
+ /**
81
+ * Methods intentionally not exposed as MCP tools.
82
+ * Add to this list with a comment explaining why.
83
+ */
84
+ const INTENTIONALLY_EXCLUDED = new Set([
85
+ "getConfig", // Client configuration — not useful as a standalone tool
86
+ "getSessionToken", // Internal auth plumbing — session managed by the transport layer
87
+ "isAuthenticated", // Auth checked at the transport layer, not exposed to LLMs
88
+ "login", // Auth handled at startup (stdio) or per-request (HTTP)
89
+ "logout", // Lifecycle managed by the server transport
90
+ "getUserTimezone", // Used internally by tools (e.g. get-tasks-by-day) — not useful standalone
91
+ ]);
92
+
93
+ describe("sunsama-api coverage", () => {
94
+ test("all public SunsamaClient methods are wrapped as MCP tools or explicitly excluded", async () => {
95
+ const clientMethods = await getSunsamaClientMethods();
96
+ const wrappedMethods = await getWrappedMethods();
97
+
98
+ const unwrapped = [...clientMethods].filter(
99
+ (m) => !wrappedMethods.has(m) && !INTENTIONALLY_EXCLUDED.has(m),
100
+ );
101
+
102
+ if (unwrapped.length > 0) {
103
+ console.error(
104
+ "\nUnwrapped SunsamaClient methods (add a tool or add to INTENTIONALLY_EXCLUDED):\n" +
105
+ unwrapped.map((m) => ` - ${m}`).join("\n"),
106
+ );
107
+ }
108
+
109
+ expect(unwrapped).toEqual([]);
110
+ });
111
+
112
+ test("INTENTIONALLY_EXCLUDED list contains only real SunsamaClient methods", async () => {
113
+ const clientMethods = await getSunsamaClientMethods();
114
+
115
+ const stale = [...INTENTIONALLY_EXCLUDED].filter(
116
+ (m) => !clientMethods.has(m),
117
+ );
118
+
119
+ if (stale.length > 0) {
120
+ console.error(
121
+ "\nStale entries in INTENTIONALLY_EXCLUDED (method no longer exists in sunsama-api):\n" +
122
+ stale.map((m) => ` - ${m}`).join("\n"),
123
+ );
124
+ }
125
+
126
+ expect(stale).toEqual([]);
127
+ });
128
+ });
package/bun.lock CHANGED
@@ -10,7 +10,7 @@
10
10
  "cors": "^2.8.5",
11
11
  "express": "^5.1.0",
12
12
  "papaparse": "^5.5.3",
13
- "sunsama-api": "0.13.1",
13
+ "sunsama-api": "0.14.0",
14
14
  "zod": "3.24.4",
15
15
  },
16
16
  "devDependencies": {
@@ -397,7 +397,7 @@
397
397
 
398
398
  "strip-bom": ["strip-bom@3.0.0", "", {}, "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA=="],
399
399
 
400
- "sunsama-api": ["sunsama-api@0.13.1", "", { "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-d60j9tLvH/HoF1K/CD8B5rphQ6UW+9XOkJHdABFVfmKCRvA+XNhN73ZzSm78dd+nRJXzaZqKG96+saN8jyBjCg=="],
400
+ "sunsama-api": ["sunsama-api@0.14.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-pXRy7naTES4/tjVHP/8H/kOgd4WaUTgNnPBT+aS5WC9Yqqiz+ajo3PT9dix8Yso0fw05lBjnC/hVPq19C00TMw=="],
401
401
 
402
402
  "term-size": ["term-size@2.2.1", "", {}, "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg=="],
403
403
 
@@ -1 +1 @@
1
- {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/auth/http.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAe9C;;GAEG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAiBtF;AAwDD,wBAAgB,uBAAuB,IAAI,IAAI,CAQ9C;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,IAAI,CAM7C;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAYxC;AAED;;;;GAIG;AACH,wBAAsB,uBAAuB,CAC3C,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,WAAW,CAAC,CAsItB"}
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/auth/http.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAgB9C;;GAEG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAiBtF;AAwDD,wBAAgB,uBAAuB,IAAI,IAAI,CAQ9C;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,IAAI,CAM7C;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAYxC;AAED;;;;GAIG;AACH,wBAAsB,uBAAuB,CAC3C,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,WAAW,CAAC,CA0ItB"}
package/dist/auth/http.js CHANGED
@@ -1,5 +1,7 @@
1
1
  import { createHash } from "crypto";
2
2
  import { SunsamaClient } from "sunsama-api/client";
3
+ import { AuthenticationError } from "./types.js";
4
+ import { loginWithRetry } from "./retry.js";
3
5
  import { getSessionConfig } from "../config/session-config.js";
4
6
  // Client cache with TTL management (keyed by credential hash for security)
5
7
  const clientCache = new Map();
@@ -18,12 +20,12 @@ export function parseBasicAuth(authHeader) {
18
20
  const credentials = Buffer.from(base64Credentials, 'base64').toString('ascii');
19
21
  const colonIndex = credentials.indexOf(':');
20
22
  if (colonIndex === -1) {
21
- throw new Error("Invalid Basic Auth format");
23
+ throw new AuthenticationError("Invalid Basic Auth format");
22
24
  }
23
25
  const email = credentials.substring(0, colonIndex);
24
26
  const password = credentials.substring(colonIndex + 1);
25
27
  if (!email || password === undefined) {
26
- throw new Error("Invalid Basic Auth format");
28
+ throw new AuthenticationError("Invalid Basic Auth format");
27
29
  }
28
30
  return { email, password };
29
31
  }
@@ -115,12 +117,12 @@ export function cleanupAllClients() {
115
117
  */
116
118
  export async function authenticateHttpRequest(authHeader) {
117
119
  if (!authHeader) {
118
- throw new Error("Authorization header required (Basic or Bearer)");
120
+ throw new AuthenticationError("Authorization header required (Basic or Bearer)");
119
121
  }
120
122
  const isBearer = authHeader.startsWith('Bearer ');
121
123
  const isBasic = authHeader.startsWith('Basic ');
122
124
  if (!isBearer && !isBasic) {
123
- throw new Error("Authorization header must be Basic or Bearer");
125
+ throw new AuthenticationError("Authorization header must be Basic or Bearer");
124
126
  }
125
127
  const now = Date.now();
126
128
  let cacheKey;
@@ -128,7 +130,7 @@ export async function authenticateHttpRequest(authHeader) {
128
130
  if (isBearer) {
129
131
  const token = authHeader.replace('Bearer ', '').trim();
130
132
  if (!token) {
131
- throw new Error("Invalid Bearer token");
133
+ throw new AuthenticationError("Invalid Bearer token");
132
134
  }
133
135
  cacheKey = getTokenCacheKey(token);
134
136
  identifier = 'token-user';
@@ -213,7 +215,12 @@ export async function authenticateHttpRequest(authHeader) {
213
215
  const authPromise = (async () => {
214
216
  try {
215
217
  const sunsamaClient = new SunsamaClient();
216
- await sunsamaClient.login(email, password);
218
+ try {
219
+ await loginWithRetry(sunsamaClient, email, password);
220
+ }
221
+ catch (err) {
222
+ throw new AuthenticationError("Login failed: invalid credentials", err);
223
+ }
217
224
  const sessionData = {
218
225
  sunsamaClient,
219
226
  email,
@@ -0,0 +1,8 @@
1
+ import { SunsamaClient } from "sunsama-api/client";
2
+ /**
3
+ * Calls sunsamaClient.login() with exponential backoff on 429 rate limit errors.
4
+ * Makes up to 4 attempts total (initial + 3 retries) with delays of 5s, 15s, 45s.
5
+ * Non-429 errors are rethrown immediately without retrying.
6
+ */
7
+ export declare function loginWithRetry(client: SunsamaClient, email: string, password: string): Promise<void>;
8
+ //# sourceMappingURL=retry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../../src/auth/retry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAKnD;;;;GAIG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,aAAa,EACrB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAoBf"}
@@ -0,0 +1,25 @@
1
+ import { SunsamaClient } from "sunsama-api/client";
2
+ import { SunsamaAuthError } from "sunsama-api/errors";
3
+ const RETRY_DELAYS = [1_000, 5_000, 15_000]; // ms
4
+ /**
5
+ * Calls sunsamaClient.login() with exponential backoff on 429 rate limit errors.
6
+ * Makes up to 4 attempts total (initial + 3 retries) with delays of 5s, 15s, 45s.
7
+ * Non-429 errors are rethrown immediately without retrying.
8
+ */
9
+ export async function loginWithRetry(client, email, password) {
10
+ for (let attempt = 0; attempt <= RETRY_DELAYS.length; attempt++) {
11
+ try {
12
+ await client.login(email, password);
13
+ return;
14
+ }
15
+ catch (err) {
16
+ const isRateLimit = err instanceof SunsamaAuthError && err.message.includes("429");
17
+ if (!isRateLimit || attempt === RETRY_DELAYS.length) {
18
+ throw err;
19
+ }
20
+ const delay = RETRY_DELAYS[attempt];
21
+ console.error(`[Auth] Rate limited (429). Retrying in ${delay / 1000}s (attempt ${attempt + 1}/${RETRY_DELAYS.length})`);
22
+ await new Promise((resolve) => setTimeout(resolve, delay));
23
+ }
24
+ }
25
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"stdio.d.ts","sourceRoot":"","sources":["../../src/auth/stdio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAOnD;;;;GAIG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,aAAa,CAAC,CAoBlE;AAED;;;;GAIG;AACH,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,aAAa,CAAC,CAMrE"}
1
+ {"version":3,"file":"stdio.d.ts","sourceRoot":"","sources":["../../src/auth/stdio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAQnD;;;;GAIG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,aAAa,CAAC,CAoBlE;AAED;;;;GAIG;AACH,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,aAAa,CAAC,CAMrE"}
@@ -1,4 +1,5 @@
1
1
  import { SunsamaClient } from "sunsama-api/client";
2
+ import { loginWithRetry } from "./retry.js";
2
3
  /**
3
4
  * Cached authentication promise to prevent concurrent auth attempts
4
5
  */
@@ -21,7 +22,7 @@ export async function initializeStdioAuth() {
21
22
  throw new Error("Sunsama credentials not configured. Please set SUNSAMA_SESSION_TOKEN or both SUNSAMA_EMAIL and SUNSAMA_PASSWORD environment variables.");
22
23
  }
23
24
  const sunsamaClient = new SunsamaClient();
24
- await sunsamaClient.login(process.env.SUNSAMA_EMAIL, process.env.SUNSAMA_PASSWORD);
25
+ await loginWithRetry(sunsamaClient, process.env.SUNSAMA_EMAIL, process.env.SUNSAMA_PASSWORD);
25
26
  return sunsamaClient;
26
27
  }
27
28
  /**
@@ -8,4 +8,11 @@ export interface SessionData extends Record<string, unknown> {
8
8
  createdAt: number;
9
9
  lastAccessedAt: number;
10
10
  }
11
+ /**
12
+ * Error thrown when authentication fails (missing/invalid credentials or login failure).
13
+ * Used to distinguish auth failures (401) from other server errors (500) in HTTP transport.
14
+ */
15
+ export declare class AuthenticationError extends Error {
16
+ constructor(message: string, cause?: unknown);
17
+ }
11
18
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD;;GAEG;AACH,MAAM,WAAW,WAAY,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC1D,aAAa,EAAE,aAAa,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;CACxB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD;;GAEG;AACH,MAAM,WAAW,WAAY,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC1D,aAAa,EAAE,aAAa,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;;GAGG;AACH,qBAAa,mBAAoB,SAAQ,KAAK;gBAChC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;CAO7C"}
@@ -1 +1,14 @@
1
1
  import { SunsamaClient } from "sunsama-api/client";
2
+ /**
3
+ * Error thrown when authentication fails (missing/invalid credentials or login failure).
4
+ * Used to distinguish auth failures (401) from other server errors (500) in HTTP transport.
5
+ */
6
+ export class AuthenticationError extends Error {
7
+ constructor(message, cause) {
8
+ super(message);
9
+ this.name = "AuthenticationError";
10
+ if (cause !== undefined) {
11
+ this.cause = cause;
12
+ }
13
+ }
14
+ }
@@ -4,7 +4,7 @@
4
4
  * VERSION is automatically synced from package.json by scripts/sync-version.ts
5
5
  * when running `bun run version`
6
6
  */
7
- export declare const VERSION = "0.17.0";
7
+ export declare const VERSION = "0.18.0";
8
8
  export declare const SERVER_NAME = "Sunsama API Server";
9
9
  export declare const PACKAGE_NAME = "mcp-sunsama";
10
10
  //# sourceMappingURL=constants.d.ts.map
package/dist/constants.js CHANGED
@@ -4,6 +4,6 @@
4
4
  * VERSION is automatically synced from package.json by scripts/sync-version.ts
5
5
  * when running `bun run version`
6
6
  */
7
- export const VERSION = "0.17.0";
7
+ export const VERSION = "0.18.0";
8
8
  export const SERVER_NAME = "Sunsama API Server";
9
9
  export const PACKAGE_NAME = "mcp-sunsama";
package/dist/main.js CHANGED
@@ -11,29 +11,23 @@ import { VERSION, SERVER_NAME } from "./constants.js";
11
11
  const server = new McpServer({
12
12
  name: SERVER_NAME,
13
13
  version: VERSION,
14
- instructions: `
15
- This MCP server provides access to the Sunsama API for task and project management.
16
-
17
- Supports both stdio and HTTP stream transports.
18
-
19
- Available tools:
20
- - User operations: get current user information
21
- - Task operations: get tasks by day, get backlog tasks, get archived tasks, get task by ID
22
- - Task mutations: create tasks, mark complete, delete tasks, reschedule tasks, update planned time, update task notes, update task due date, update task text, update task stream assignment
23
- - Stream operations: get streams/channels for the user's group
24
-
25
- Authentication:
26
- - Stdio transport: Uses SUNSAMA_EMAIL and SUNSAMA_PASSWORD from environment
27
- - HTTP transport: Requires HTTP Basic Auth with Sunsama credentials
28
- `.trim(),
14
+ instructions: [
15
+ "This MCP server provides access to the Sunsama API for task and project management.",
16
+ "Supports both stdio and HTTP stream transports.",
17
+ "",
18
+ "Available tools:",
19
+ ...allTools.map((t) => `- ${t.name}: ${t.description}`),
20
+ "",
21
+ "Authentication:",
22
+ "- Stdio transport: Uses SUNSAMA_EMAIL + SUNSAMA_PASSWORD, or SUNSAMA_SESSION_TOKEN",
23
+ "- HTTP transport: HTTP Basic Auth (email:password) or Bearer token",
24
+ ].join("\n"),
29
25
  });
30
26
  // Register all tools
31
27
  allTools.forEach((tool) => {
32
28
  server.registerTool(tool.name, {
33
29
  description: tool.description,
34
- inputSchema: "shape" in tool.parameters
35
- ? tool.parameters.shape
36
- : tool.parameters,
30
+ inputSchema: tool.inputSchema,
37
31
  }, tool.execute);
38
32
  });
39
33
  // Register resources
package/dist/schemas.d.ts CHANGED
@@ -240,6 +240,16 @@ export declare const deleteTaskSchema: z.ZodObject<{
240
240
  limitResponsePayload?: boolean | undefined;
241
241
  wasTaskMerged?: boolean | undefined;
242
242
  }>;
243
+ export declare const updateTaskUncompleteSchema: z.ZodObject<{
244
+ taskId: z.ZodString;
245
+ limitResponsePayload: z.ZodOptional<z.ZodBoolean>;
246
+ }, "strip", z.ZodTypeAny, {
247
+ taskId: string;
248
+ limitResponsePayload?: boolean | undefined;
249
+ }, {
250
+ taskId: string;
251
+ limitResponsePayload?: boolean | undefined;
252
+ }>;
243
253
  export declare const updateTaskSnoozeDateSchema: z.ZodObject<{
244
254
  taskId: z.ZodString;
245
255
  newDay: z.ZodString;
@@ -579,6 +589,78 @@ export declare const streamSchema: z.ZodObject<{
579
589
  isActive: boolean;
580
590
  color?: string | undefined;
581
591
  }>;
592
+ export declare const reorderTaskSchema: z.ZodObject<{
593
+ taskId: z.ZodString;
594
+ position: z.ZodNumber;
595
+ day: z.ZodString;
596
+ timezone: z.ZodOptional<z.ZodString>;
597
+ }, "strip", z.ZodTypeAny, {
598
+ day: string;
599
+ taskId: string;
600
+ position: number;
601
+ timezone?: string | undefined;
602
+ }, {
603
+ day: string;
604
+ taskId: string;
605
+ position: number;
606
+ timezone?: string | undefined;
607
+ }>;
608
+ /**
609
+ * Calendar Event Operation Schemas
610
+ */
611
+ export declare const createCalendarEventSchema: z.ZodObject<{
612
+ title: z.ZodString;
613
+ startDate: z.ZodString;
614
+ endDate: z.ZodString;
615
+ description: z.ZodOptional<z.ZodString>;
616
+ calendarId: z.ZodOptional<z.ZodString>;
617
+ service: z.ZodOptional<z.ZodEnum<["google", "microsoft"]>>;
618
+ streamIds: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
619
+ visibility: z.ZodOptional<z.ZodEnum<["private", "public", "default", "confidential"]>>;
620
+ transparency: z.ZodOptional<z.ZodEnum<["opaque", "transparent"]>>;
621
+ isAllDay: z.ZodOptional<z.ZodBoolean>;
622
+ seedTaskId: z.ZodOptional<z.ZodString>;
623
+ }, "strip", z.ZodTypeAny, {
624
+ title: string;
625
+ startDate: string;
626
+ endDate: string;
627
+ service?: "google" | "microsoft" | undefined;
628
+ streamIds?: string[] | undefined;
629
+ description?: string | undefined;
630
+ calendarId?: string | undefined;
631
+ visibility?: "private" | "public" | "default" | "confidential" | undefined;
632
+ transparency?: "opaque" | "transparent" | undefined;
633
+ isAllDay?: boolean | undefined;
634
+ seedTaskId?: string | undefined;
635
+ }, {
636
+ title: string;
637
+ startDate: string;
638
+ endDate: string;
639
+ service?: "google" | "microsoft" | undefined;
640
+ streamIds?: string[] | undefined;
641
+ description?: string | undefined;
642
+ calendarId?: string | undefined;
643
+ visibility?: "private" | "public" | "default" | "confidential" | undefined;
644
+ transparency?: "opaque" | "transparent" | undefined;
645
+ isAllDay?: boolean | undefined;
646
+ seedTaskId?: string | undefined;
647
+ }>;
648
+ export declare const updateCalendarEventSchema: z.ZodObject<{
649
+ eventId: z.ZodString;
650
+ update: z.ZodRecord<z.ZodString, z.ZodUnknown>;
651
+ isInviteeStatusUpdate: z.ZodOptional<z.ZodBoolean>;
652
+ skipReorder: z.ZodOptional<z.ZodBoolean>;
653
+ }, "strip", z.ZodTypeAny, {
654
+ eventId: string;
655
+ update: Record<string, unknown>;
656
+ isInviteeStatusUpdate?: boolean | undefined;
657
+ skipReorder?: boolean | undefined;
658
+ }, {
659
+ eventId: string;
660
+ update: Record<string, unknown>;
661
+ isInviteeStatusUpdate?: boolean | undefined;
662
+ skipReorder?: boolean | undefined;
663
+ }>;
582
664
  /**
583
665
  * API Response Schemas
584
666
  */
@@ -839,6 +921,7 @@ export type GetUserInput = z.infer<typeof getUserSchema>;
839
921
  export type GetStreamsInput = z.infer<typeof getStreamsSchema>;
840
922
  export type CreateTaskInput = z.infer<typeof createTaskSchema>;
841
923
  export type UpdateTaskCompleteInput = z.infer<typeof updateTaskCompleteSchema>;
924
+ export type UpdateTaskUncompleteInput = z.infer<typeof updateTaskUncompleteSchema>;
842
925
  export type DeleteTaskInput = z.infer<typeof deleteTaskSchema>;
843
926
  export type UpdateTaskSnoozeDateInput = z.infer<typeof updateTaskSnoozeDateSchema>;
844
927
  export type UpdateTaskBacklogInput = z.infer<typeof updateTaskBacklogSchema>;
@@ -852,6 +935,9 @@ export type UpdateSubtaskTitleInput = z.infer<typeof updateSubtaskTitleSchema>;
852
935
  export type CompleteSubtaskInput = z.infer<typeof completeSubtaskSchema>;
853
936
  export type UncompleteSubtaskInput = z.infer<typeof uncompleteSubtaskSchema>;
854
937
  export type AddSubtaskInput = z.infer<typeof addSubtaskSchema>;
938
+ export type ReorderTaskInput = z.infer<typeof reorderTaskSchema>;
939
+ export type CreateCalendarEventInput = z.infer<typeof createCalendarEventSchema>;
940
+ export type UpdateCalendarEventInput = z.infer<typeof updateCalendarEventSchema>;
855
941
  export type User = z.infer<typeof userSchema>;
856
942
  export type Task = z.infer<typeof taskSchema>;
857
943
  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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"}