mcp-sunsama 0.15.1 → 0.15.3

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 (106) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/auth/http.d.ts.map +1 -1
  3. package/dist/auth/http.js +8 -3
  4. package/dist/auth/stdio.d.ts +1 -1
  5. package/dist/auth/stdio.d.ts.map +1 -1
  6. package/dist/auth/stdio.js +1 -1
  7. package/dist/auth/types.d.ts +1 -1
  8. package/dist/auth/types.d.ts.map +1 -1
  9. package/dist/auth/types.js +1 -1
  10. package/dist/main.js +1 -1
  11. package/dist/resources/index.js +1 -1
  12. package/dist/utils/client-resolver.d.ts +1 -1
  13. package/dist/utils/client-resolver.d.ts.map +1 -1
  14. package/dist/utils/client-resolver.js +1 -1
  15. package/dist/utils/task-filters.d.ts +1 -1
  16. package/dist/utils/task-filters.d.ts.map +1 -1
  17. package/dist/utils/task-trimmer.d.ts +1 -1
  18. package/dist/utils/task-trimmer.d.ts.map +1 -1
  19. package/package.json +1 -1
  20. package/src/auth/http.ts +1 -1
  21. package/src/auth/stdio.ts +1 -1
  22. package/src/auth/types.ts +1 -1
  23. package/src/main.ts +1 -1
  24. package/src/tools/task-tools.ts +1 -1
  25. package/src/utils/client-resolver.ts +1 -1
  26. package/src/utils/task-filters.ts +1 -1
  27. package/src/utils/task-trimmer.ts +1 -1
  28. package/tsconfig.json +2 -1
  29. package/dist/__tests__/integration/http-transport.test.d.ts +0 -2
  30. package/dist/__tests__/integration/http-transport.test.d.ts.map +0 -1
  31. package/dist/__tests__/integration/http-transport.test.js +0 -265
  32. package/dist/__tests__/unit/auth/http.test.d.ts +0 -2
  33. package/dist/__tests__/unit/auth/http.test.d.ts.map +0 -1
  34. package/dist/__tests__/unit/auth/http.test.js +0 -211
  35. package/dist/__tests__/unit/config/session-config.test.d.ts +0 -2
  36. package/dist/__tests__/unit/config/session-config.test.d.ts.map +0 -1
  37. package/dist/__tests__/unit/config/session-config.test.js +0 -134
  38. package/dist/__tests__/unit/session/session-manager.test.d.ts +0 -2
  39. package/dist/__tests__/unit/session/session-manager.test.d.ts.map +0 -1
  40. package/dist/__tests__/unit/session/session-manager.test.js +0 -192
  41. package/dist/context/index.d.ts +0 -9
  42. package/dist/context/index.d.ts.map +0 -1
  43. package/dist/context/index.js +0 -5
  44. package/dist/src/auth/http.d.ts +0 -23
  45. package/dist/src/auth/http.d.ts.map +0 -1
  46. package/dist/src/auth/http.js +0 -165
  47. package/dist/src/auth/stdio.d.ts +0 -13
  48. package/dist/src/auth/stdio.d.ts.map +0 -1
  49. package/dist/src/auth/stdio.js +0 -28
  50. package/dist/src/auth/types.d.ts +0 -11
  51. package/dist/src/auth/types.d.ts.map +0 -1
  52. package/dist/src/auth/types.js +0 -1
  53. package/dist/src/config/session-config.d.ts +0 -49
  54. package/dist/src/config/session-config.d.ts.map +0 -1
  55. package/dist/src/config/session-config.js +0 -54
  56. package/dist/src/config/transport.d.ts +0 -12
  57. package/dist/src/config/transport.d.ts.map +0 -1
  58. package/dist/src/config/transport.js +0 -27
  59. package/dist/src/main.d.ts +0 -3
  60. package/dist/src/main.d.ts.map +0 -1
  61. package/dist/src/main.js +0 -58
  62. package/dist/src/resources/index.d.ts +0 -13
  63. package/dist/src/resources/index.d.ts.map +0 -1
  64. package/dist/src/resources/index.js +0 -166
  65. package/dist/src/schemas.d.ts +0 -658
  66. package/dist/src/schemas.d.ts.map +0 -1
  67. package/dist/src/schemas.js +0 -193
  68. package/dist/src/schemas.test.d.ts +0 -2
  69. package/dist/src/schemas.test.d.ts.map +0 -1
  70. package/dist/src/schemas.test.js +0 -857
  71. package/dist/src/session/session-manager.d.ts +0 -53
  72. package/dist/src/session/session-manager.d.ts.map +0 -1
  73. package/dist/src/session/session-manager.js +0 -141
  74. package/dist/src/tools/index.d.ts +0 -11
  75. package/dist/src/tools/index.d.ts.map +0 -1
  76. package/dist/src/tools/index.js +0 -12
  77. package/dist/src/tools/shared.d.ts +0 -63
  78. package/dist/src/tools/shared.d.ts.map +0 -1
  79. package/dist/src/tools/shared.js +0 -84
  80. package/dist/src/tools/stream-tools.d.ts +0 -13
  81. package/dist/src/tools/stream-tools.d.ts.map +0 -1
  82. package/dist/src/tools/stream-tools.js +0 -12
  83. package/dist/src/tools/task-tools.d.ts +0 -91
  84. package/dist/src/tools/task-tools.d.ts.map +0 -1
  85. package/dist/src/tools/task-tools.js +0 -271
  86. package/dist/src/tools/user-tools.d.ts +0 -13
  87. package/dist/src/tools/user-tools.d.ts.map +0 -1
  88. package/dist/src/tools/user-tools.js +0 -13
  89. package/dist/src/transports/http.d.ts +0 -8
  90. package/dist/src/transports/http.d.ts.map +0 -1
  91. package/dist/src/transports/http.js +0 -245
  92. package/dist/src/transports/stdio.d.ts +0 -3
  93. package/dist/src/transports/stdio.d.ts.map +0 -1
  94. package/dist/src/transports/stdio.js +0 -11
  95. package/dist/src/utils/client-resolver.d.ts +0 -8
  96. package/dist/src/utils/client-resolver.d.ts.map +0 -1
  97. package/dist/src/utils/client-resolver.js +0 -23
  98. package/dist/src/utils/task-filters.d.ts +0 -29
  99. package/dist/src/utils/task-filters.d.ts.map +0 -1
  100. package/dist/src/utils/task-filters.js +0 -42
  101. package/dist/src/utils/task-trimmer.d.ts +0 -50
  102. package/dist/src/utils/task-trimmer.d.ts.map +0 -1
  103. package/dist/src/utils/task-trimmer.js +0 -59
  104. package/dist/src/utils/to-tsv.d.ts +0 -8
  105. package/dist/src/utils/to-tsv.d.ts.map +0 -1
  106. package/dist/src/utils/to-tsv.js +0 -64
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # mcp-sunsama
2
2
 
3
+ ## 0.15.3
4
+
5
+ ### Patch Changes
6
+
7
+ - b9cd204: Fix TypeScript build output by excluding **tests** from compilation. Version 0.15.2 broke because TypeScript was compiling both src/ and **tests**/ directories, causing files to be output to dist/src/ instead of dist/. Now excludes **tests** so production code builds directly to dist/.
8
+
9
+ ## 0.15.2
10
+
11
+ ### Patch Changes
12
+
13
+ - 6128d4c: Fix Node.js v20 compatibility by using sunsama-api subpath exports. Updates all imports to use explicit subpath exports ('sunsama-api/client' and 'sunsama-api/types') instead of root import, resolving ESM/CommonJS interoperability issues.
14
+
3
15
  ## 0.15.1
4
16
 
5
17
  ### Patch Changes
@@ -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,CAUtF;AA+CD,wBAAgB,uBAAuB,IAAI,IAAI,CAQ9C;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,IAAI,CAM7C;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAYxC;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,CAC3C,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,WAAW,CAAC,CAiEtB"}
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;AA+CD,wBAAgB,uBAAuB,IAAI,IAAI,CAQ9C;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,IAAI,CAM7C;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAYxC;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,CAC3C,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,WAAW,CAAC,CAiEtB"}
package/dist/auth/http.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { createHash } from "crypto";
2
- import { SunsamaClient } from "sunsama-api";
2
+ import { SunsamaClient } from "sunsama-api/client";
3
3
  import { getSessionConfig } from "../config/session-config.js";
4
4
  // Client cache with TTL management (keyed by credential hash for security)
5
5
  const clientCache = new Map();
@@ -16,8 +16,13 @@ const CLEANUP_INTERVAL = sessionConfig.CLEANUP_INTERVAL;
16
16
  export function parseBasicAuth(authHeader) {
17
17
  const base64Credentials = authHeader.replace('Basic ', '');
18
18
  const credentials = Buffer.from(base64Credentials, 'base64').toString('ascii');
19
- const [email, password] = credentials.split(':');
20
- if (!email || !password) {
19
+ const colonIndex = credentials.indexOf(':');
20
+ if (colonIndex === -1) {
21
+ throw new Error("Invalid Basic Auth format");
22
+ }
23
+ const email = credentials.substring(0, colonIndex);
24
+ const password = credentials.substring(colonIndex + 1);
25
+ if (!email || password === undefined) {
21
26
  throw new Error("Invalid Basic Auth format");
22
27
  }
23
28
  return { email, password };
@@ -1,4 +1,4 @@
1
- import { SunsamaClient } from "sunsama-api";
1
+ import { SunsamaClient } from "sunsama-api/client";
2
2
  /**
3
3
  * Initialize stdio authentication using environment variables
4
4
  * @throws {Error} If credentials are missing or authentication fails
@@ -1 +1 @@
1
- {"version":3,"file":"stdio.d.ts","sourceRoot":"","sources":["../../src/auth/stdio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAO5C;;;GAGG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,aAAa,CAAC,CAWlE;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;AAOnD;;;GAGG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,aAAa,CAAC,CAWlE;AAED;;;;GAIG;AACH,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,aAAa,CAAC,CAMrE"}
@@ -1,4 +1,4 @@
1
- import { SunsamaClient } from "sunsama-api";
1
+ import { SunsamaClient } from "sunsama-api/client";
2
2
  /**
3
3
  * Cached authentication promise to prevent concurrent auth attempts
4
4
  */
@@ -1,4 +1,4 @@
1
- import { SunsamaClient } from "sunsama-api";
1
+ import { SunsamaClient } from "sunsama-api/client";
2
2
  /**
3
3
  * Session data interface for HTTP transport
4
4
  */
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C;;GAEG;AACH,MAAM,WAAW,WAAY,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC1D,aAAa,EAAE,aAAa,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,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,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;CACxB"}
@@ -1 +1 @@
1
- import { SunsamaClient } from "sunsama-api";
1
+ import { SunsamaClient } from "sunsama-api/client";
package/dist/main.js CHANGED
@@ -9,7 +9,7 @@ import { apiDocumentationResource } from "./resources/index.js";
9
9
  (async () => {
10
10
  const server = new McpServer({
11
11
  name: "Sunsama API Server",
12
- version: "0.15.0",
12
+ version: "0.15.3",
13
13
  instructions: `
14
14
  This MCP server provides access to the Sunsama API for task and project management.
15
15
 
@@ -151,7 +151,7 @@ Uses HTTP Basic Auth headers (per-request authentication):
151
151
  - \`SUNSAMA_PASSWORD\`: Sunsama account password
152
152
 
153
153
  ### Optional Configuration
154
- - \`TRANSPORT_TYPE\`: "stdio" (default) | "httpStream"
154
+ - \`TRANSPORT_MODE\`: "stdio" (default) | "http"
155
155
  - \`PORT\`: Server port for HTTP transport (default: 3002)
156
156
 
157
157
  ## Error Handling
@@ -1,4 +1,4 @@
1
- import { SunsamaClient } from "sunsama-api";
1
+ import { SunsamaClient } from "sunsama-api/client";
2
2
  /**
3
3
  * Gets the appropriate SunsamaClient instance based on context
4
4
  * - HTTP transport: Uses session-scoped client from request
@@ -1 +1 @@
1
- {"version":3,"file":"client-resolver.d.ts","sourceRoot":"","sources":["../../src/utils/client-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAK5C;;;;GAIG;AACH,wBAAsB,SAAS,CAAC,OAAO,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,aAAa,CAAC,CAgBrE"}
1
+ {"version":3,"file":"client-resolver.d.ts","sourceRoot":"","sources":["../../src/utils/client-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAKnD;;;;GAIG;AACH,wBAAsB,SAAS,CAAC,OAAO,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,aAAa,CAAC,CAgBrE"}
@@ -1,4 +1,4 @@
1
- import { SunsamaClient } from "sunsama-api";
1
+ import { SunsamaClient } from "sunsama-api/client";
2
2
  import { getGlobalSunsamaClient } from "../auth/stdio.js";
3
3
  import { sessionManager } from "../transports/http.js";
4
4
  /**
@@ -1,4 +1,4 @@
1
- import type { Task } from "sunsama-api";
1
+ import type { Task } from "sunsama-api/types";
2
2
  import type { CompletionFilter } from "../schemas.js";
3
3
  /**
4
4
  * Filters an array of tasks based on completion status.
@@ -1 +1 @@
1
- {"version":3,"file":"task-filters.d.ts","sourceRoot":"","sources":["../../src/utils/task-filters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEtD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,gBAAgB,GAAG,IAAI,EAAE,CAoBvF"}
1
+ {"version":3,"file":"task-filters.d.ts","sourceRoot":"","sources":["../../src/utils/task-filters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEtD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,gBAAgB,GAAG,IAAI,EAAE,CAoBvF"}
@@ -1,4 +1,4 @@
1
- import type { Task, TaskIntegration } from "sunsama-api";
1
+ import type { Task, TaskIntegration } from "sunsama-api/types";
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.
@@ -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,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"}
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,mBAAmB,CAAC;AAE/D;;;;;;;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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-sunsama",
3
- "version": "0.15.1",
3
+ "version": "0.15.3",
4
4
  "description": "MCP server for Sunsama API integration",
5
5
  "type": "module",
6
6
  "private": false,
package/src/auth/http.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { createHash } from "crypto";
2
- import { SunsamaClient } from "sunsama-api";
2
+ import { SunsamaClient } from "sunsama-api/client";
3
3
  import type { SessionData } from "./types.js";
4
4
  import { getSessionConfig } from "../config/session-config.js";
5
5
 
package/src/auth/stdio.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { SunsamaClient } from "sunsama-api";
1
+ import { SunsamaClient } from "sunsama-api/client";
2
2
 
3
3
  /**
4
4
  * Cached authentication promise to prevent concurrent auth attempts
package/src/auth/types.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { SunsamaClient } from "sunsama-api";
1
+ import { SunsamaClient } from "sunsama-api/client";
2
2
 
3
3
  /**
4
4
  * Session data interface for HTTP transport
package/src/main.ts CHANGED
@@ -10,7 +10,7 @@ import { apiDocumentationResource } from "./resources/index.js";
10
10
  (async () => {
11
11
  const server = new McpServer({
12
12
  name: "Sunsama API Server",
13
- version: "0.15.1",
13
+ version: "0.15.3",
14
14
  instructions: `
15
15
  This MCP server provides access to the Sunsama API for task and project management.
16
16
 
@@ -1,4 +1,4 @@
1
- import type { CreateTaskOptions } from "sunsama-api";
1
+ import type { CreateTaskOptions } from "sunsama-api/types";
2
2
  import {
3
3
  type CreateTaskInput,
4
4
  createTaskSchema,
@@ -1,4 +1,4 @@
1
- import { SunsamaClient } from "sunsama-api";
1
+ import { SunsamaClient } from "sunsama-api/client";
2
2
  import { getGlobalSunsamaClient } from "../auth/stdio.js";
3
3
  import type { SessionData } from "../auth/types.js";
4
4
  import { sessionManager } from "../transports/http.js";
@@ -1,4 +1,4 @@
1
- import type { Task } from "sunsama-api";
1
+ import type { Task } from "sunsama-api/types";
2
2
  import type { CompletionFilter } from "../schemas.js";
3
3
 
4
4
  /**
@@ -1,4 +1,4 @@
1
- import type { Task, TaskIntegration } from "sunsama-api";
1
+ import type { Task, TaskIntegration } from "sunsama-api/types";
2
2
 
3
3
  /**
4
4
  * Trimmed task type containing only essential properties for API responses.
package/tsconfig.json CHANGED
@@ -31,6 +31,7 @@
31
31
  },
32
32
  "exclude": [
33
33
  "dist",
34
- "node_modules"
34
+ "node_modules",
35
+ "__tests__"
35
36
  ]
36
37
  }
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=http-transport.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"http-transport.test.d.ts","sourceRoot":"","sources":["../../../__tests__/integration/http-transport.test.ts"],"names":[],"mappings":""}
@@ -1,265 +0,0 @@
1
- import { describe, test, expect, beforeAll, afterAll } from "bun:test";
2
- const SUNSAMA_EMAIL = process.env.SUNSAMA_EMAIL;
3
- const SUNSAMA_PASSWORD = process.env.SUNSAMA_PASSWORD;
4
- const TEST_PORT = process.env.TEST_PORT || "3099";
5
- const BASE_URL = `http://localhost:${TEST_PORT}`;
6
- const shouldRunIntegrationTests = Boolean(SUNSAMA_EMAIL && SUNSAMA_PASSWORD);
7
- // Helper to create Basic Auth header
8
- function createAuthHeader(email, password) {
9
- return `Basic ${Buffer.from(`${email}:${password}`).toString("base64")}`;
10
- }
11
- // Helper to make MCP requests with properly typed responses
12
- async function mcpRequest(method, params = {}, auth) {
13
- const headers = {
14
- "Content-Type": "application/json",
15
- "Accept": "application/json, text/event-stream",
16
- };
17
- if (auth) {
18
- headers["Authorization"] = auth;
19
- }
20
- const response = await fetch(`${BASE_URL}/mcp`, {
21
- method: "POST",
22
- headers,
23
- body: JSON.stringify({
24
- jsonrpc: "2.0",
25
- method,
26
- params,
27
- id: Math.floor(Math.random() * 10000),
28
- }),
29
- });
30
- return response.json();
31
- }
32
- describe.skipIf(!shouldRunIntegrationTests)("HTTP Transport Integration Tests", () => {
33
- beforeAll(() => {
34
- console.log("\n🔧 Integration Test Setup");
35
- console.log("═".repeat(50));
36
- console.log(`Test server: ${BASE_URL}`);
37
- console.log(`Using credentials: ${SUNSAMA_EMAIL}`);
38
- console.log("Note: Server must be running separately on port", TEST_PORT);
39
- console.log("═".repeat(50) + "\n");
40
- });
41
- afterAll(() => {
42
- console.log("\n✅ Integration tests completed\n");
43
- });
44
- describe("Server Health", () => {
45
- test("should return server info", async () => {
46
- const response = await fetch(`${BASE_URL}/`);
47
- const data = await response.json();
48
- expect(response.status).toBe(200);
49
- expect(data.name).toBe("mcp-sunsama");
50
- expect(data.transport).toBe("http");
51
- expect(data).toHaveProperty("activeSessions");
52
- expect(data).toHaveProperty("version");
53
- });
54
- });
55
- describe("Authentication", () => {
56
- test("should authenticate with valid credentials", async () => {
57
- const auth = createAuthHeader(SUNSAMA_EMAIL, SUNSAMA_PASSWORD);
58
- const result = await mcpRequest("tools/list", {}, auth);
59
- expect(result.error).toBeUndefined();
60
- expect(result.result).toBeDefined();
61
- expect(result.result.tools).toBeArray();
62
- expect(result.result.tools.length).toBeGreaterThan(0);
63
- });
64
- test("should reject invalid credentials", async () => {
65
- const auth = createAuthHeader("wrong@example.com", "wrongpassword");
66
- const result = await mcpRequest("tools/list", {}, auth);
67
- expect(result.error).toBeDefined();
68
- expect(result.error.code).toBe(-32000);
69
- expect(result.error.message).toContain("Authentication failed");
70
- });
71
- test("should reject missing authorization", async () => {
72
- const result = await mcpRequest("tools/list", {});
73
- expect(result.error).toBeDefined();
74
- expect(result.error.code).toBe(-32000);
75
- });
76
- });
77
- describe("Session Caching", () => {
78
- test("should cache authenticated sessions", async () => {
79
- const auth = createAuthHeader(SUNSAMA_EMAIL, SUNSAMA_PASSWORD);
80
- // First request - creates session
81
- const result1 = await mcpRequest("tools/call", {
82
- name: "get-user",
83
- arguments: {},
84
- }, auth);
85
- expect(result1.error).toBeUndefined();
86
- expect(result1.result).toBeDefined();
87
- // Second request - should use cached session
88
- const result2 = await mcpRequest("tools/call", {
89
- name: "get-user",
90
- arguments: {},
91
- }, auth);
92
- expect(result2.error).toBeUndefined();
93
- expect(result2.result).toBeDefined();
94
- // Both should return the same user
95
- const user1 = JSON.parse(result1.result.content[0].text);
96
- const user2 = JSON.parse(result2.result.content[0].text);
97
- expect(user1._id).toBe(user2._id);
98
- expect(user1.email).toBe(user2.email);
99
- });
100
- test("should create separate sessions for different credentials", async () => {
101
- if (!process.env.SUNSAMA_EMAIL_2 || !process.env.SUNSAMA_PASSWORD_2) {
102
- console.log("⏭️ Skipping multiple user test (SUNSAMA_EMAIL_2 not set)");
103
- return;
104
- }
105
- const auth1 = createAuthHeader(SUNSAMA_EMAIL, SUNSAMA_PASSWORD);
106
- const auth2 = createAuthHeader(process.env.SUNSAMA_EMAIL_2, process.env.SUNSAMA_PASSWORD_2);
107
- const result1 = await mcpRequest("tools/call", {
108
- name: "get-user",
109
- arguments: {},
110
- }, auth1);
111
- const result2 = await mcpRequest("tools/call", {
112
- name: "get-user",
113
- arguments: {},
114
- }, auth2);
115
- expect(result1.error).toBeUndefined();
116
- expect(result2.error).toBeUndefined();
117
- const user1 = JSON.parse(result1.result.content[0].text);
118
- const user2 = JSON.parse(result2.result.content[0].text);
119
- // Should be different users
120
- expect(user1.email).not.toBe(user2.email);
121
- });
122
- });
123
- describe("Tool Execution", () => {
124
- const auth = createAuthHeader(SUNSAMA_EMAIL, SUNSAMA_PASSWORD);
125
- test("should execute get-user tool", async () => {
126
- const result = await mcpRequest("tools/call", {
127
- name: "get-user",
128
- arguments: {},
129
- }, auth);
130
- expect(result.error).toBeUndefined();
131
- expect(result.result.content).toBeArray();
132
- expect(result.result.content[0].type).toBe("text");
133
- const user = JSON.parse(result.result.content[0].text);
134
- expect(user).toHaveProperty("_id");
135
- expect(user).toHaveProperty("email");
136
- expect(user).toHaveProperty("profile");
137
- expect(user.email).toBe(SUNSAMA_EMAIL);
138
- });
139
- test("should execute get-streams tool", async () => {
140
- const result = await mcpRequest("tools/call", {
141
- name: "get-streams",
142
- arguments: {},
143
- }, auth);
144
- expect(result.error).toBeUndefined();
145
- expect(result.result.content).toBeArray();
146
- const response = result.result.content[0].text;
147
- // Response should be TSV format
148
- expect(response).toContain("\t"); // TSV uses tabs
149
- });
150
- test("should execute get-tasks-backlog tool", async () => {
151
- const result = await mcpRequest("tools/call", {
152
- name: "get-tasks-backlog",
153
- arguments: {},
154
- }, auth);
155
- expect(result.error).toBeUndefined();
156
- expect(result.result.content).toBeArray();
157
- const response = result.result.content[0].text;
158
- // Response should be TSV format
159
- expect(typeof response).toBe("string");
160
- });
161
- test("should execute get-tasks-by-day tool", async () => {
162
- const today = new Date().toISOString().split("T")[0]; // YYYY-MM-DD
163
- const result = await mcpRequest("tools/call", {
164
- name: "get-tasks-by-day",
165
- arguments: {
166
- day: today,
167
- completionFilter: "all",
168
- },
169
- }, auth);
170
- expect(result.error).toBeUndefined();
171
- expect(result.result.content).toBeArray();
172
- const response = result.result.content[0].text;
173
- expect(typeof response).toBe("string");
174
- });
175
- test("should handle tool errors gracefully", async () => {
176
- const result = await mcpRequest("tools/call", {
177
- name: "get-task-by-id",
178
- arguments: {
179
- taskId: "non-existent-task-id-12345",
180
- },
181
- }, auth);
182
- // Should return an error or empty result, not crash
183
- expect(result).toBeDefined();
184
- });
185
- });
186
- describe("Concurrent Requests", () => {
187
- test("should handle multiple concurrent requests", async () => {
188
- const auth = createAuthHeader(SUNSAMA_EMAIL, SUNSAMA_PASSWORD);
189
- // Make 10 concurrent requests
190
- const promises = Array.from({ length: 10 }, () => mcpRequest("tools/call", {
191
- name: "get-user",
192
- arguments: {},
193
- }, auth));
194
- const results = await Promise.all(promises);
195
- // All should succeed
196
- results.forEach((result) => {
197
- expect(result.error).toBeUndefined();
198
- expect(result.result).toBeDefined();
199
- });
200
- // All should return the same user
201
- const users = results.map((r) => JSON.parse(r.result.content[0].text));
202
- const firstUserId = users[0]._id;
203
- users.forEach((user) => {
204
- expect(user._id).toBe(firstUserId);
205
- });
206
- });
207
- test("should handle concurrent requests with different credentials", async () => {
208
- if (!process.env.SUNSAMA_EMAIL_2 || !process.env.SUNSAMA_PASSWORD_2) {
209
- console.log("⏭️ Skipping concurrent multi-user test");
210
- return;
211
- }
212
- const auth1 = createAuthHeader(SUNSAMA_EMAIL, SUNSAMA_PASSWORD);
213
- const auth2 = createAuthHeader(process.env.SUNSAMA_EMAIL_2, process.env.SUNSAMA_PASSWORD_2);
214
- // 5 requests for each user, interleaved
215
- const promises = Array.from({ length: 10 }, (_, i) => mcpRequest("tools/call", {
216
- name: "get-user",
217
- arguments: {},
218
- }, i % 2 === 0 ? auth1 : auth2));
219
- const results = await Promise.all(promises);
220
- // All should succeed
221
- results.forEach((result) => {
222
- expect(result.error).toBeUndefined();
223
- });
224
- // Check that we got two different users
225
- const users = results.map((r) => JSON.parse(r.result.content[0].text));
226
- const uniqueEmails = new Set(users.map((u) => u.email));
227
- expect(uniqueEmails.size).toBe(2);
228
- });
229
- });
230
- describe("Error Recovery", () => {
231
- test("should recover from transient failures", async () => {
232
- const auth = createAuthHeader(SUNSAMA_EMAIL, SUNSAMA_PASSWORD);
233
- // Make a valid request
234
- const result1 = await mcpRequest("tools/call", {
235
- name: "get-user",
236
- arguments: {},
237
- }, auth);
238
- expect(result1.error).toBeUndefined();
239
- // Make an invalid request
240
- const result2 = await mcpRequest("tools/call", {
241
- name: "invalid-tool-name",
242
- arguments: {},
243
- }, auth);
244
- expect(result2.error).toBeDefined();
245
- // Make another valid request - should still work
246
- const result3 = await mcpRequest("tools/call", {
247
- name: "get-user",
248
- arguments: {},
249
- }, auth);
250
- expect(result3.error).toBeUndefined();
251
- });
252
- });
253
- });
254
- // Print helpful message if tests are skipped
255
- if (!shouldRunIntegrationTests) {
256
- console.log("\n" + "⏭️".repeat(25));
257
- console.log("⏭️ Integration tests SKIPPED");
258
- console.log("⏭️");
259
- console.log("⏭️ To run integration tests:");
260
- console.log("⏭️ 1. Set SUNSAMA_EMAIL and SUNSAMA_PASSWORD in .env");
261
- console.log("⏭️ 2. Start server: TRANSPORT_MODE=http PORT=3099 bun dev");
262
- console.log("⏭️ 3. Run tests: bun test:integration");
263
- console.log("⏭️");
264
- console.log("⏭️".repeat(25) + "\n");
265
- }
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=http.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"http.test.d.ts","sourceRoot":"","sources":["../../../../__tests__/unit/auth/http.test.ts"],"names":[],"mappings":""}