mcp-sunsama 0.15.4 → 0.16.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # mcp-sunsama
2
2
 
3
+ ## 0.16.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 5df00f4: Bump sunsama-api dependency from 0.12.0 to 0.12.1
8
+ - 14c0713: Fix update-task-notes tool failing with MCP error -32603. Removed Zod `.refine()` from schema which was causing MCP SDK to fail parsing the tool parameters. XOR validation between html/markdown is now handled at runtime.
9
+
10
+ ## 0.16.0
11
+
12
+ ### Minor Changes
13
+
14
+ - 56872df: Add GitHub and Gmail integration support to create-task tool
15
+
16
+ This minor release adds support for creating Sunsama tasks with GitHub and Gmail integrations, enabling users to convert GitHub issues/PRs and Gmail emails into tasks with proper linking and metadata.
17
+
18
+ **New Features:**
19
+
20
+ - Added `TaskGithubIntegration` schema with all required fields (id, repositoryOwnerLogin, repositoryName, number, type, url)
21
+ - Added `TaskGmailIntegration` schema with all required fields (id, messageId, accountId, url)
22
+ - Updated `create-task` tool to accept optional `integration` parameter
23
+ - Implemented discriminated union pattern for type-safe integration handling
24
+ - Full TypeScript support with Zod schema validation
25
+
26
+ **Migration:**
27
+ No breaking changes. This is a purely additive feature that extends existing functionality. The integration parameter is optional, so existing code will continue to work without modifications.
28
+
3
29
  ## 0.15.4
4
30
 
5
31
  ### Patch Changes
package/CLAUDE.md CHANGED
@@ -28,6 +28,31 @@ bun run version # Apply changesets and update version
28
28
  bun run release # Build and publish to npm
29
29
  ```
30
30
 
31
+ ## Contribution Workflow
32
+
33
+ **IMPORTANT**: When making changes that affect package users, always create a changeset.
34
+
35
+ ### When to Create a Changeset
36
+ - ✅ New user-facing features or tools
37
+ - ✅ Bug fixes that affect npm package users
38
+ - ✅ API changes or breaking changes
39
+ - ✅ Dependency updates that change behavior
40
+
41
+ ### When NOT to Create a Changeset
42
+ - ❌ Infrastructure/deployment changes (CI/CD, Docker, Smithery config)
43
+ - ❌ Internal refactoring with no behavior changes
44
+ - ❌ Documentation updates
45
+ - ❌ Development tooling changes
46
+
47
+ ### Standard Workflow
48
+ 1. Create a branch: `git checkout -b {type}/{short-name}`
49
+ 2. Make changes and test: `bun test && bun run typecheck`
50
+ 3. **Create a changeset**: `bun run changeset` (if changes affect users)
51
+ 4. Commit with conventional format: `git commit -m "fix: description"`
52
+ 5. Push and create PR
53
+
54
+ See `CONTRIBUTING.md` for full details.
55
+
31
56
  ## Architecture Overview
32
57
 
33
58
  ### Dual Transport MCP Server
@@ -87,8 +112,16 @@ All tools use Zod schemas from `schemas.ts`:
87
112
  - Automatic TypeScript inference
88
113
  - Comprehensive parameter documentation
89
114
  - Union types for completion filters
90
- - XOR schema patterns for mutually exclusive parameters using `.refine()` for MCP Inspector compatibility
91
- - Example: `update-task-notes` requires either `html` OR `markdown`, but not both
115
+ - **Important**: Avoid using `.refine()` on schemas - it transforms `ZodObject` into `ZodEffects` which the MCP SDK cannot parse (results in empty `properties`). Handle complex validation (e.g., XOR between fields) in the tool's `execute` function instead.
116
+ - Example: `update-task-notes` requires either `html` OR `markdown`, validated at runtime
117
+ - Discriminated unions for task integrations (GitHub, Gmail)
118
+
119
+ ### Integration Support
120
+ The `create-task` tool supports external integrations:
121
+ - **GitHub Integration**: Link tasks to GitHub issues or pull requests
122
+ - **Gmail Integration**: Link tasks to Gmail emails
123
+ - Uses discriminated union pattern for type-safe integration handling
124
+ - Integration parameter is optional to maintain backward compatibility
92
125
 
93
126
  ## Key Patterns
94
127
 
@@ -149,7 +182,7 @@ src/
149
182
  ├── tools/
150
183
  │ ├── shared.ts # Common utilities and tool wrapper patterns
151
184
  │ ├── user-tools.ts # User operations (get-user)
152
- │ ├── task-tools.ts # Task operations (14 tools)
185
+ │ ├── task-tools.ts # Task operations (15 tools)
153
186
  │ ├── stream-tools.ts # Stream operations (get-streams)
154
187
  │ └── index.ts # Export all tools
155
188
  ├── resources/
@@ -193,7 +226,7 @@ __tests__/
193
226
 
194
227
  **Resource-Based Organization**:
195
228
  - **User Tools**: Single tool for user operations
196
- - **Task Tools**: 14 tools organized by function (query, lifecycle, update)
229
+ - **Task Tools**: 15 tools organized by function (query, lifecycle, update)
197
230
  - **Stream Tools**: Single tool for stream operations
198
231
 
199
232
  **Type Safety Improvements**:
@@ -227,7 +260,7 @@ Tests are organized in the `__tests__/` directory following standard conventions
227
260
  ## Important Notes
228
261
 
229
262
  ### Version Synchronization
230
- Always keep FastMCP server version in `src/main.ts` (line 19) synchronized with `package.json` version.
263
+ The MCP server version in `src/constants.ts` is automatically synced from `package.json` when running `bun run version`.
231
264
 
232
265
  ### Environment Variables
233
266
  Required for stdio transport:
@@ -244,7 +277,7 @@ Optional:
244
277
  ### Task Operations
245
278
  Full CRUD support:
246
279
  - **Read**: `get-tasks-by-day`, `get-tasks-backlog`, `get-archived-tasks`, `get-task-by-id`, `get-streams`
247
- - **Write**: `create-task`, `update-task-complete`, `update-task-planned-time`, `update-task-notes`, `update-task-snooze-date`, `update-task-backlog`, `update-task-stream`, `delete-task`
280
+ - **Write**: `create-task` (with GitHub/Gmail integration support), `update-task-complete`, `update-task-planned-time`, `update-task-notes`, `update-task-snooze-date`, `update-task-backlog`, `update-task-stream`, `update-task-text`, `update-task-due-date`, `delete-task`
248
281
 
249
282
  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.
250
283
 
@@ -254,12 +287,11 @@ Configure different server variants in `mcp-inspector.json` for testing various
254
287
 
255
288
  ## Version Management
256
289
 
257
- **IMPORTANT**: Keep the FastMCP server version in sync with package.json version.
290
+ Version is managed automatically via changesets. When you run `bun run version`:
291
+ 1. Changesets updates `package.json` version
292
+ 2. `scripts/sync-version.ts` automatically syncs the version to `src/constants.ts`
258
293
 
259
- When updating the version:
260
- 1. Update `package.json` version (done automatically by changesets)
261
- 2. Manually update the FastMCP server version in `src/main.ts` (line 19)
262
- 3. Both versions must be identical for consistency
294
+ No manual version updates needed.
263
295
 
264
296
  ## Git Rules
265
297
 
package/CONTRIBUTING.md CHANGED
@@ -55,12 +55,24 @@ Example: `feat/add-task-labels`
55
55
  bun run build
56
56
  ```
57
57
 
58
- 5. Create a changeset for your changes:
58
+ 5. Create a changeset for your changes (if needed):
59
59
  ```bash
60
60
  bun run changeset
61
61
  ```
62
62
  Follow the prompts to describe your changes.
63
63
 
64
+ **When to create a changeset:**
65
+ - ✅ New user-facing features or tools
66
+ - ✅ Bug fixes that affect npm package users
67
+ - ✅ API changes or breaking changes
68
+ - ✅ Dependency updates that change behavior
69
+
70
+ **When NOT to create a changeset:**
71
+ - ❌ Infrastructure/deployment changes (CI/CD, Docker, Smithery config)
72
+ - ❌ Internal refactoring with no behavior changes
73
+ - ❌ Documentation updates
74
+ - ❌ Development tooling changes
75
+
64
76
  6. Commit your changes using conventional commit format:
65
77
  ```bash
66
78
  git add .
@@ -155,11 +167,9 @@ This project uses [changesets](https://github.com/changesets/changesets) for ver
155
167
  bun run version # Apply changesets and update package.json
156
168
  ```
157
169
 
158
- **IMPORTANT**: After running this command, manually update the MCP server version in `src/main.ts` (line ~19) to match the new version in `package.json`:
170
+ **IMPORTANT**: After this command, manually update the version in `src/constants.ts` to match `package.json`:
159
171
  ```typescript
160
- const server = new FastMCP({
161
- name: "Sunsama API Server",
162
- version: "X.Y.Z", // <-- Update this to match package.json
172
+ export const VERSION = "X.Y.Z"; // <-- Update to match package.json
163
173
  ```
164
174
 
165
175
  3. **Pre-Release Validation**
@@ -177,7 +187,6 @@ This project uses [changesets](https://github.com/changesets/changesets) for ver
177
187
  Verify the commit includes:
178
188
  - `package.json` - version bump
179
189
  - `CHANGELOG.md` - generated changelog
180
- - `src/main.ts` - MCP server version update
181
190
  - Removed changeset files from `.changeset/`
182
191
 
183
192
  5. **Publish to NPM**
@@ -199,7 +208,11 @@ This project uses [changesets](https://github.com/changesets/changesets) for ver
199
208
 
200
209
  #### Version Synchronization
201
210
 
202
- The MCP server version in `src/main.ts` must always match the version in `package.json`. This ensures clients receive accurate version information during the MCP handshake.
211
+ **IMPORTANT**: When updating the version, you must update it in TWO places:
212
+ 1. `package.json` - The npm package version
213
+ 2. `src/constants.ts` - The `VERSION` constant
214
+
215
+ This ensures the MCP server reports the correct version to clients during the handshake.
203
216
 
204
217
  #### Troubleshooting Releases
205
218
 
package/README.md CHANGED
@@ -2,10 +2,14 @@
2
2
 
3
3
  A Model Context Protocol (MCP) server that provides comprehensive task management capabilities through the Sunsama API. This server enables AI assistants to access Sunsama tasks, create new tasks, mark tasks complete, and manage your productivity workflow.
4
4
 
5
+ <a href="https://glama.ai/mcp/servers/@robertn702/mcp-sunsama">
6
+ <img width="380" height="200" src="https://glama.ai/mcp/servers/@robertn702/mcp-sunsama/badge" />
7
+ </a>
8
+
5
9
  ## Features
6
10
 
7
11
  ### Task Management
8
- - **Create Tasks** - Create new tasks with notes, time estimates, due dates, and stream assignments
12
+ - **Create Tasks** - Create new tasks with notes, time estimates, due dates, stream assignments, and GitHub/Gmail integrations
9
13
  - **Read Tasks** - Get tasks by day with completion filtering, access backlog tasks, retrieve archived task history
10
14
  - **Update Tasks** - Mark tasks as complete with custom timestamps, reschedule tasks or move to backlog
11
15
  - **Delete Tasks** - Permanently remove tasks from your workspace
@@ -110,7 +114,7 @@ Add this configuration to your Claude Desktop MCP settings:
110
114
  ## API Tools
111
115
 
112
116
  ### Task Management
113
- - `create-task` - Create new tasks with optional properties
117
+ - `create-task` - Create new tasks with optional properties including GitHub issue/PR and Gmail integration
114
118
  - `get-tasks-by-day` - Get tasks for a specific day with completion filtering
115
119
  - `get-tasks-backlog` - Get backlog tasks
116
120
  - `get-archived-tasks` - Get archived tasks with pagination (includes hasMore flag for LLM context)
@@ -129,6 +133,74 @@ Add this configuration to your Claude Desktop MCP settings:
129
133
  - `get-user` - Get current user information
130
134
  - `get-streams` - Get streams/channels for project organization
131
135
 
136
+ ### Integration Examples
137
+
138
+ The `create-task` tool supports linking tasks to external services like GitHub and Gmail.
139
+
140
+ #### GitHub Integration
141
+
142
+ Link a task to a GitHub issue:
143
+ ```json
144
+ {
145
+ "text": "Fix authentication bug",
146
+ "integration": {
147
+ "service": "github",
148
+ "identifier": {
149
+ "id": "I_kwDOO4SCuM7VTB4n",
150
+ "repositoryOwnerLogin": "robertn702",
151
+ "repositoryName": "mcp-sunsama",
152
+ "number": 42,
153
+ "type": "Issue",
154
+ "url": "https://github.com/robertn702/mcp-sunsama/issues/42",
155
+ "__typename": "TaskGithubIntegrationIdentifier"
156
+ },
157
+ "__typename": "TaskGithubIntegration"
158
+ }
159
+ }
160
+ ```
161
+
162
+ Link a task to a GitHub pull request:
163
+ ```json
164
+ {
165
+ "text": "Review API refactoring PR",
166
+ "integration": {
167
+ "service": "github",
168
+ "identifier": {
169
+ "id": "PR_kwDOO4SCuM7VTB5o",
170
+ "repositoryOwnerLogin": "robertn702",
171
+ "repositoryName": "mcp-sunsama",
172
+ "number": 15,
173
+ "type": "PullRequest",
174
+ "url": "https://github.com/robertn702/mcp-sunsama/pull/15",
175
+ "__typename": "TaskGithubIntegrationIdentifier"
176
+ },
177
+ "__typename": "TaskGithubIntegration"
178
+ }
179
+ }
180
+ ```
181
+
182
+ #### Gmail Integration
183
+
184
+ Link a task to a Gmail email:
185
+ ```json
186
+ {
187
+ "text": "Respond to project update email",
188
+ "integration": {
189
+ "service": "gmail",
190
+ "identifier": {
191
+ "id": "19a830b40fd7ab7d",
192
+ "messageId": "19a830b40fd7ab7d",
193
+ "accountId": "user@example.com",
194
+ "url": "https://mail.google.com/mail/u/user@example.com/#inbox/19a830b40fd7ab7d",
195
+ "__typename": "TaskGmailIntegrationIdentifier"
196
+ },
197
+ "__typename": "TaskGmailIntegration"
198
+ }
199
+ }
200
+ ```
201
+
202
+ **Note**: All integration parameters are optional. Tasks can be created without integrations for standard task management.
203
+
132
204
  ## Development
133
205
 
134
206
  ### Running in Development
@@ -171,7 +243,7 @@ src/
171
243
  ├── tools/
172
244
  │ ├── shared.ts # Common utilities and patterns
173
245
  │ ├── user-tools.ts # User operations (get-user)
174
- │ ├── task-tools.ts # Task operations (14 tools)
246
+ │ ├── task-tools.ts # Task operations (15 tools)
175
247
  │ ├── stream-tools.ts # Stream operations (get-streams)
176
248
  │ └── index.ts # Export all tools
177
249
  ├── resources/
package/bun.lock CHANGED
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "lockfileVersion": 1,
3
+ "configVersion": 0,
3
4
  "workspaces": {
4
5
  "": {
5
6
  "name": "mcp-sunsama",
@@ -9,7 +10,7 @@
9
10
  "cors": "^2.8.5",
10
11
  "express": "^5.1.0",
11
12
  "papaparse": "^5.5.3",
12
- "sunsama-api": "0.11.2",
13
+ "sunsama-api": "0.12.1",
13
14
  "zod": "3.24.4",
14
15
  },
15
16
  "devDependencies": {
@@ -396,7 +397,7 @@
396
397
 
397
398
  "strip-bom": ["strip-bom@3.0.0", "", {}, "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA=="],
398
399
 
399
- "sunsama-api": ["sunsama-api@0.11.2", "", { "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-tyBrCai6Z0jEmRXkwGY+0PlXJTAwE3IJXXRCDcGFwpFPxFO5fyxw6mqM/RhYu7OGhP3AF7w4CikvEOBDaFXvKA=="],
400
+ "sunsama-api": ["sunsama-api@0.12.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-F2GLJjanAeboP4vYg3VIKP8xxQ/8LLqHhNFx3lm9oONOSvLzVAXEJlwonESuUI/iIf93b2i/jYCJ/2guoUhRYQ=="],
400
401
 
401
402
  "term-size": ["term-size@2.2.1", "", {}, "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg=="],
402
403
 
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Application constants
3
+ *
4
+ * VERSION is automatically synced from package.json by scripts/sync-version.ts
5
+ * when running `bun run version`
6
+ */
7
+ export declare const VERSION = "0.16.1";
8
+ export declare const SERVER_NAME = "Sunsama API Server";
9
+ export declare const PACKAGE_NAME = "mcp-sunsama";
10
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,OAAO,WAAW,CAAC;AAChC,eAAO,MAAM,WAAW,uBAAuB,CAAC;AAChD,eAAO,MAAM,YAAY,gBAAgB,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Application constants
3
+ *
4
+ * VERSION is automatically synced from package.json by scripts/sync-version.ts
5
+ * when running `bun run version`
6
+ */
7
+ export const VERSION = "0.16.1";
8
+ export const SERVER_NAME = "Sunsama API Server";
9
+ export const PACKAGE_NAME = "mcp-sunsama";
package/dist/main.js CHANGED
@@ -5,11 +5,12 @@ import { setupStdioTransport } from "./transports/stdio.js";
5
5
  import { setupHttpTransport } from "./transports/http.js";
6
6
  import { allTools } from "./tools/index.js";
7
7
  import { apiDocumentationResource } from "./resources/index.js";
8
+ import { VERSION, SERVER_NAME } from "./constants.js";
8
9
  // Async IIFE for top-level await and error handling
9
10
  (async () => {
10
11
  const server = new McpServer({
11
- name: "Sunsama API Server",
12
- version: "0.15.4",
12
+ name: SERVER_NAME,
13
+ version: VERSION,
13
14
  instructions: `
14
15
  This MCP server provides access to the Sunsama API for task and project management.
15
16
 
package/dist/schemas.d.ts CHANGED
@@ -54,6 +54,101 @@ export declare const createTaskSchema: z.ZodObject<{
54
54
  snoozeUntil: z.ZodOptional<z.ZodString>;
55
55
  private: z.ZodOptional<z.ZodBoolean>;
56
56
  taskId: z.ZodOptional<z.ZodString>;
57
+ integration: z.ZodOptional<z.ZodDiscriminatedUnion<"service", [z.ZodObject<{
58
+ service: z.ZodLiteral<"github">;
59
+ identifier: z.ZodObject<{
60
+ id: z.ZodString;
61
+ repositoryOwnerLogin: z.ZodString;
62
+ repositoryName: z.ZodString;
63
+ number: z.ZodNumber;
64
+ type: z.ZodEnum<["Issue", "PullRequest"]>;
65
+ url: z.ZodString;
66
+ __typename: z.ZodLiteral<"TaskGithubIntegrationIdentifier">;
67
+ }, "strip", z.ZodTypeAny, {
68
+ number: number;
69
+ type: "Issue" | "PullRequest";
70
+ id: string;
71
+ url: string;
72
+ repositoryOwnerLogin: string;
73
+ repositoryName: string;
74
+ __typename: "TaskGithubIntegrationIdentifier";
75
+ }, {
76
+ number: number;
77
+ type: "Issue" | "PullRequest";
78
+ id: string;
79
+ url: string;
80
+ repositoryOwnerLogin: string;
81
+ repositoryName: string;
82
+ __typename: "TaskGithubIntegrationIdentifier";
83
+ }>;
84
+ __typename: z.ZodLiteral<"TaskGithubIntegration">;
85
+ }, "strip", z.ZodTypeAny, {
86
+ __typename: "TaskGithubIntegration";
87
+ service: "github";
88
+ identifier: {
89
+ number: number;
90
+ type: "Issue" | "PullRequest";
91
+ id: string;
92
+ url: string;
93
+ repositoryOwnerLogin: string;
94
+ repositoryName: string;
95
+ __typename: "TaskGithubIntegrationIdentifier";
96
+ };
97
+ }, {
98
+ __typename: "TaskGithubIntegration";
99
+ service: "github";
100
+ identifier: {
101
+ number: number;
102
+ type: "Issue" | "PullRequest";
103
+ id: string;
104
+ url: string;
105
+ repositoryOwnerLogin: string;
106
+ repositoryName: string;
107
+ __typename: "TaskGithubIntegrationIdentifier";
108
+ };
109
+ }>, z.ZodObject<{
110
+ service: z.ZodLiteral<"gmail">;
111
+ identifier: z.ZodObject<{
112
+ id: z.ZodString;
113
+ messageId: z.ZodString;
114
+ accountId: z.ZodString;
115
+ url: z.ZodString;
116
+ __typename: z.ZodLiteral<"TaskGmailIntegrationIdentifier">;
117
+ }, "strip", z.ZodTypeAny, {
118
+ id: string;
119
+ url: string;
120
+ __typename: "TaskGmailIntegrationIdentifier";
121
+ messageId: string;
122
+ accountId: string;
123
+ }, {
124
+ id: string;
125
+ url: string;
126
+ __typename: "TaskGmailIntegrationIdentifier";
127
+ messageId: string;
128
+ accountId: string;
129
+ }>;
130
+ __typename: z.ZodLiteral<"TaskGmailIntegration">;
131
+ }, "strip", z.ZodTypeAny, {
132
+ __typename: "TaskGmailIntegration";
133
+ service: "gmail";
134
+ identifier: {
135
+ id: string;
136
+ url: string;
137
+ __typename: "TaskGmailIntegrationIdentifier";
138
+ messageId: string;
139
+ accountId: string;
140
+ };
141
+ }, {
142
+ __typename: "TaskGmailIntegration";
143
+ service: "gmail";
144
+ identifier: {
145
+ id: string;
146
+ url: string;
147
+ __typename: "TaskGmailIntegrationIdentifier";
148
+ messageId: string;
149
+ accountId: string;
150
+ };
151
+ }>]>>;
57
152
  }, "strip", z.ZodTypeAny, {
58
153
  text: string;
59
154
  taskId?: string | undefined;
@@ -63,6 +158,29 @@ export declare const createTaskSchema: z.ZodObject<{
63
158
  dueDate?: string | undefined;
64
159
  snoozeUntil?: string | undefined;
65
160
  private?: boolean | undefined;
161
+ integration?: {
162
+ __typename: "TaskGithubIntegration";
163
+ service: "github";
164
+ identifier: {
165
+ number: number;
166
+ type: "Issue" | "PullRequest";
167
+ id: string;
168
+ url: string;
169
+ repositoryOwnerLogin: string;
170
+ repositoryName: string;
171
+ __typename: "TaskGithubIntegrationIdentifier";
172
+ };
173
+ } | {
174
+ __typename: "TaskGmailIntegration";
175
+ service: "gmail";
176
+ identifier: {
177
+ id: string;
178
+ url: string;
179
+ __typename: "TaskGmailIntegrationIdentifier";
180
+ messageId: string;
181
+ accountId: string;
182
+ };
183
+ } | undefined;
66
184
  }, {
67
185
  text: string;
68
186
  taskId?: string | undefined;
@@ -72,6 +190,29 @@ export declare const createTaskSchema: z.ZodObject<{
72
190
  dueDate?: string | undefined;
73
191
  snoozeUntil?: string | undefined;
74
192
  private?: boolean | undefined;
193
+ integration?: {
194
+ __typename: "TaskGithubIntegration";
195
+ service: "github";
196
+ identifier: {
197
+ number: number;
198
+ type: "Issue" | "PullRequest";
199
+ id: string;
200
+ url: string;
201
+ repositoryOwnerLogin: string;
202
+ repositoryName: string;
203
+ __typename: "TaskGithubIntegrationIdentifier";
204
+ };
205
+ } | {
206
+ __typename: "TaskGmailIntegration";
207
+ service: "gmail";
208
+ identifier: {
209
+ id: string;
210
+ url: string;
211
+ __typename: "TaskGmailIntegrationIdentifier";
212
+ messageId: string;
213
+ accountId: string;
214
+ };
215
+ } | undefined;
75
216
  }>;
76
217
  export declare const updateTaskCompleteSchema: z.ZodObject<{
77
218
  taskId: z.ZodString;
@@ -141,7 +282,7 @@ export declare const updateTaskPlannedTimeSchema: z.ZodObject<{
141
282
  timeEstimateMinutes: number;
142
283
  limitResponsePayload?: boolean | undefined;
143
284
  }>;
144
- export declare const updateTaskNotesSchema: z.ZodEffects<z.ZodObject<{
285
+ export declare const updateTaskNotesSchema: z.ZodObject<{
145
286
  taskId: z.ZodString;
146
287
  html: z.ZodOptional<z.ZodString>;
147
288
  markdown: z.ZodOptional<z.ZodString>;
@@ -156,16 +297,6 @@ export declare const updateTaskNotesSchema: z.ZodEffects<z.ZodObject<{
156
297
  limitResponsePayload?: boolean | undefined;
157
298
  html?: string | undefined;
158
299
  markdown?: string | undefined;
159
- }>, {
160
- taskId: string;
161
- limitResponsePayload?: boolean | undefined;
162
- html?: string | undefined;
163
- markdown?: string | undefined;
164
- }, {
165
- taskId: string;
166
- limitResponsePayload?: boolean | undefined;
167
- html?: string | undefined;
168
- markdown?: string | undefined;
169
300
  }>;
170
301
  export declare const updateTaskDueDateSchema: z.ZodObject<{
171
302
  taskId: z.ZodString;
@@ -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":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;GAEG;AAGH,eAAO,MAAM,sBAAsB,+CAIjC,CAAC;AAGH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;EAW9B,CAAC;AAGH,eAAO,MAAM,qBAAqB,gDAAe,CAAC;AAGlD,eAAO,MAAM,sBAAsB;;;;;;;;;EAOjC,CAAC;AAGH,eAAO,MAAM,iBAAiB;;;;;;EAI5B,CAAC;AAEH;;GAEG;AAGH,eAAO,MAAM,aAAa,gDAAe,CAAC;AAE1C;;GAEG;AAGH,eAAO,MAAM,gBAAgB,gDAAe,CAAC;AA8C7C;;GAEG;AAGH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAsB3B,CAAC;AAGH,eAAO,MAAM,wBAAwB;;;;;;;;;;;;EAUnC,CAAC;AAGH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;EAU3B,CAAC;AAGH,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;EAarC,CAAC;AAGH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;EAUlC,CAAC;AAGH,eAAO,MAAM,2BAA2B;;;;;;;;;;;;EAUtC,CAAC;AAKH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;EAahC,CAAC;AAGH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;EAalC,CAAC;AAGH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;EAa/B,CAAC;AAGH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;EAUjC,CAAC;AAEH;;GAEG;AAGH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;EAO5B,CAAC;AAGH,eAAO,MAAM,WAAW;;;;;;;;;;;;EAItB,CAAC;AAGH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAKrB,CAAC;AAGH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAYrB,CAAC;AAGH,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;EAQvB,CAAC;AAEH;;GAEG;AAGH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAE7B,CAAC;AAGH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAG9B,CAAC;AAGH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAGhC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;EAI9B,CAAC;AAEH;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AACrE,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AACzE,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAC3E,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AACjE,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AACzD,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE/D,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAC/D,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAC/E,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAC/D,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAC7C,OAAO,0BAA0B,CAClC,CAAC;AACF,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAC7E,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAC9C,OAAO,2BAA2B,CACnC,CAAC;AACF,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AACzE,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAC7E,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AACvE,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAE3E,MAAM,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC;AAC9C,MAAM,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC;AAC9C,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAClD,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAC9D,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAChE,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AACpE,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC"}
package/dist/schemas.js CHANGED
@@ -35,6 +35,44 @@ export const getUserSchema = z.object({});
35
35
  */
36
36
  // Get streams parameters (no parameters needed, uses cached group ID)
37
37
  export const getStreamsSchema = z.object({});
38
+ /**
39
+ * Task Integration Schemas
40
+ */
41
+ // GitHub integration identifier schema
42
+ const githubIntegrationIdentifierSchema = z.object({
43
+ id: z.string().describe("GitHub issue or PR ID"),
44
+ repositoryOwnerLogin: z.string().describe("GitHub repository owner login"),
45
+ repositoryName: z.string().describe("GitHub repository name"),
46
+ number: z.number().int().describe("GitHub issue or PR number"),
47
+ type: z.enum(["Issue", "PullRequest"]).describe("Type of GitHub item"),
48
+ url: z.string().url().describe("URL to the GitHub issue or PR"),
49
+ __typename: z.literal("TaskGithubIntegrationIdentifier"),
50
+ });
51
+ // GitHub integration schema
52
+ const githubIntegrationSchema = z.object({
53
+ service: z.literal("github"),
54
+ identifier: githubIntegrationIdentifierSchema,
55
+ __typename: z.literal("TaskGithubIntegration"),
56
+ });
57
+ // Gmail integration identifier schema
58
+ const gmailIntegrationIdentifierSchema = z.object({
59
+ id: z.string().describe("Gmail message ID"),
60
+ messageId: z.string().describe("Gmail message ID (duplicate of id)"),
61
+ accountId: z.string().describe("Gmail account ID"),
62
+ url: z.string().url().describe("URL to the Gmail message"),
63
+ __typename: z.literal("TaskGmailIntegrationIdentifier"),
64
+ });
65
+ // Gmail integration schema
66
+ const gmailIntegrationSchema = z.object({
67
+ service: z.literal("gmail"),
68
+ identifier: gmailIntegrationIdentifierSchema,
69
+ __typename: z.literal("TaskGmailIntegration"),
70
+ });
71
+ // Union schema for all task integrations
72
+ const taskIntegrationSchema = z.discriminatedUnion("service", [
73
+ githubIntegrationSchema,
74
+ gmailIntegrationSchema,
75
+ ]);
38
76
  /**
39
77
  * Task Mutation Operation Schemas
40
78
  */
@@ -48,6 +86,7 @@ export const createTaskSchema = z.object({
48
86
  snoozeUntil: z.string().optional().describe("Snooze until date string (ISO format) - the date the task is scheduled for"),
49
87
  private: z.boolean().optional().describe("Whether the task is private"),
50
88
  taskId: z.string().optional().describe("Custom task ID (auto-generated if not provided)"),
89
+ integration: taskIntegrationSchema.optional().describe("Integration information for linking task to external services (GitHub, Gmail, etc.)"),
51
90
  });
52
91
  // Update task complete parameters
53
92
  export const updateTaskCompleteSchema = z.object({
@@ -80,20 +119,14 @@ export const updateTaskPlannedTimeSchema = z.object({
80
119
  timeEstimateMinutes: z.number().int().min(0).describe("Time estimate in minutes (use 0 to clear the time estimate)"),
81
120
  limitResponsePayload: z.boolean().optional().describe("Whether to limit the response payload size"),
82
121
  });
83
- // Update task notes parameters with XOR content validation
122
+ // Update task notes parameters
123
+ // Note: XOR validation between html/markdown is done in the tool execute function
124
+ // to keep the schema as a plain ZodObject (required for MCP SDK compatibility)
84
125
  export const updateTaskNotesSchema = z.object({
85
126
  taskId: z.string().min(1, "Task ID is required").describe("The ID of the task to update notes for"),
86
127
  html: z.string().optional().describe("HTML content for the task notes (mutually exclusive with markdown)"),
87
128
  markdown: z.string().optional().describe("Markdown content for the task notes (mutually exclusive with html)"),
88
129
  limitResponsePayload: z.boolean().optional().describe("Whether to limit the response payload size (defaults to true)"),
89
- }).refine((data) => {
90
- // Exactly one of html or markdown must be provided
91
- const hasHtml = data.html !== undefined;
92
- const hasMarkdown = data.markdown !== undefined;
93
- return hasHtml !== hasMarkdown; // XOR: exactly one must be true
94
- }, {
95
- message: "Exactly one of 'html' or 'markdown' must be provided",
96
- path: [], // This will show the error at the root level
97
130
  });
98
131
  // Update task due date parameters
99
132
  export const updateTaskDueDateSchema = z.object({
@@ -1 +1 @@
1
- {"version":3,"file":"task-tools.d.ts","sourceRoot":"","sources":["../../src/tools/task-tools.ts"],"names":[],"mappings":"AA0CA,eAAO,MAAM,mBAAmB;;;;;CAU9B,CAAC;AAEH,eAAO,MAAM,iBAAiB;;;;;CAqB5B,CAAC;AAEH,eAAO,MAAM,oBAAoB;;;;;CA2B/B,CAAC;AAEH,eAAO,MAAM,eAAe;;;;;CAS1B,CAAC;AAGH,eAAO,MAAM,cAAc;;;;;CAoCzB,CAAC;AAEH,eAAO,MAAM,cAAc;;;;;CAqBzB,CAAC;AAGH,eAAO,MAAM,sBAAsB;;;;;CAqBjC,CAAC;AAEH,eAAO,MAAM,wBAAwB;;;;;CA6BnC,CAAC;AAEH,eAAO,MAAM,qBAAqB;;;;;CA2BhC,CAAC;AAEH,eAAO,MAAM,yBAAyB;;;;;CAsBpC,CAAC;AAEH,eAAO,MAAM,mBAAmB;;;;;CAiC9B,CAAC;AAEH,eAAO,MAAM,qBAAqB;;;;;CAsBhC,CAAC;AAEH,eAAO,MAAM,kBAAkB;;;;;CA8B7B,CAAC;AAEH,eAAO,MAAM,oBAAoB;;;;;CAsB/B,CAAC;AAGH,eAAO,MAAM,SAAS;;;;;GAoBrB,CAAC"}
1
+ {"version":3,"file":"task-tools.d.ts","sourceRoot":"","sources":["../../src/tools/task-tools.ts"],"names":[],"mappings":"AA0CA,eAAO,MAAM,mBAAmB;;;;;CAU9B,CAAC;AAEH,eAAO,MAAM,iBAAiB;;;;;CAqB5B,CAAC;AAEH,eAAO,MAAM,oBAAoB;;;;;CA2B/B,CAAC;AAEH,eAAO,MAAM,eAAe;;;;;CAS1B,CAAC;AAGH,eAAO,MAAM,cAAc;;;;;CAsCzB,CAAC;AAEH,eAAO,MAAM,cAAc;;;;;CAqBzB,CAAC;AAGH,eAAO,MAAM,sBAAsB;;;;;CAqBjC,CAAC;AAEH,eAAO,MAAM,wBAAwB;;;;;CA6BnC,CAAC;AAEH,eAAO,MAAM,qBAAqB;;;;;CA2BhC,CAAC;AAEH,eAAO,MAAM,yBAAyB;;;;;CAsBpC,CAAC;AAEH,eAAO,MAAM,mBAAmB;;;;;CAwC9B,CAAC;AAEH,eAAO,MAAM,qBAAqB;;;;;CAsBhC,CAAC;AAEH,eAAO,MAAM,kBAAkB;;;;;CA8B7B,CAAC;AAEH,eAAO,MAAM,oBAAoB;;;;;CAsB/B,CAAC;AAGH,eAAO,MAAM,SAAS;;;;;GAoBrB,CAAC"}
@@ -64,7 +64,7 @@ export const createTaskTool = withTransportClient({
64
64
  name: "create-task",
65
65
  description: "Create a new task with optional properties",
66
66
  parameters: createTaskSchema,
67
- execute: async ({ text, notes, streamIds, timeEstimate, dueDate, snoozeUntil, private: isPrivate, taskId, }, context) => {
67
+ execute: async ({ text, notes, streamIds, timeEstimate, dueDate, snoozeUntil, private: isPrivate, taskId, integration, }, context) => {
68
68
  const options = {};
69
69
  if (notes)
70
70
  options.notes = notes;
@@ -80,6 +80,8 @@ export const createTaskTool = withTransportClient({
80
80
  options.private = isPrivate;
81
81
  if (taskId)
82
82
  options.taskId = taskId;
83
+ if (integration)
84
+ options.integration = integration;
83
85
  const result = await context.client.createTask(text, options);
84
86
  return formatJsonResponse({
85
87
  success: result.success,
@@ -178,6 +180,12 @@ export const updateTaskNotesTool = withTransportClient({
178
180
  description: "Update the notes content for a task",
179
181
  parameters: updateTaskNotesSchema,
180
182
  execute: async ({ taskId, html, markdown, limitResponsePayload }, context) => {
183
+ // XOR validation: exactly one of html or markdown must be provided
184
+ const hasHtml = html !== undefined;
185
+ const hasMarkdown = markdown !== undefined;
186
+ if (hasHtml === hasMarkdown) {
187
+ throw new Error("Exactly one of 'html' or 'markdown' must be provided");
188
+ }
181
189
  const content = html
182
190
  ? { type: "html", value: html }
183
191
  : { type: "markdown", value: markdown };
@@ -1 +1 @@
1
- {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/transports/http.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AASpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE9D,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAI/D,eAAO,MAAM,cAAc,gBAAuB,CAAC;AAgCnD,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,OAAO,CAAC,eAAe,EAAE;IAAE,aAAa,EAAE,MAAM,CAAA;CAAE,CAAC,iBA4O5D"}
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/transports/http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAcpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE9D,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAG/D,eAAO,MAAM,cAAc,gBAAuB,CAAC;AAgCnD,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,OAAO,CAAC,eAAe,EAAE;IAAE,aAAa,EAAE,MAAM,CAAA;CAAE,CAAC,iBA4O5D"}
@@ -1,12 +1,13 @@
1
- import express from "express";
2
- import cors from "cors";
3
- import { randomUUID } from "node:crypto";
4
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
5
2
  import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
6
3
  import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
7
- import { authenticateHttpRequest, startClientCacheCleanup, stopClientCacheCleanup, cleanupAllClients, } from "../auth/http.js";
8
- import { SessionManager } from "../session/session-manager.js";
4
+ import cors from "cors";
5
+ import express from "express";
6
+ import { randomUUID } from "node:crypto";
7
+ import { authenticateHttpRequest, cleanupAllClients, startClientCacheCleanup, stopClientCacheCleanup, } from "../auth/http.js";
9
8
  import { getSessionConfig } from "../config/session-config.js";
9
+ import { PACKAGE_NAME, VERSION } from "../constants.js";
10
+ import { SessionManager } from "../session/session-manager.js";
10
11
  // Unified session management
11
12
  export const sessionManager = new SessionManager();
12
13
  // Configuration - loaded from environment
@@ -52,8 +53,8 @@ export async function setupHttpTransport(server, config) {
52
53
  // Health check endpoint
53
54
  app.get("/", (req, res) => {
54
55
  res.json({
55
- name: "mcp-sunsama",
56
- version: "0.15.0",
56
+ name: PACKAGE_NAME,
57
+ version: VERSION,
57
58
  transport: "http",
58
59
  activeSessions: sessionManager.getSessionCount(),
59
60
  });
package/glama.json ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "$schema": "https://glama.ai/mcp/schemas/server.json",
3
+ "maintainers": [
4
+ "robertn702"
5
+ ]
6
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-sunsama",
3
- "version": "0.15.4",
3
+ "version": "0.16.1",
4
4
  "description": "MCP server for Sunsama API integration",
5
5
  "type": "module",
6
6
  "private": false,
@@ -16,15 +16,17 @@
16
16
  "test:integration": "bun test --test-name-pattern 'Integration Tests'",
17
17
  "test:all": "bun test",
18
18
  "test:watch": "bun test --watch --test-name-pattern '^(?!.*Integration Tests).*$'",
19
- "typecheck": "bunx tsc --noEmit",
20
- "typecheck:watch": "bunx tsc --noEmit --watch",
21
- "build": "bunx tsc",
19
+ "typecheck": "tsc --noEmit",
20
+ "typecheck:watch": "tsc --noEmit --watch",
21
+ "clean": "rm -rf dist",
22
+ "build": "tsc",
23
+ "build:clean": "npm run clean && npm run build",
22
24
  "postbuild": "chmod +x dist/main.js",
23
25
  "inspect": "bunx @modelcontextprotocol/inspector --config ./mcp-inspector.json --server sunsama",
24
26
  "changeset": "changeset",
25
- "version": "changeset version",
26
- "release": "bun run build && changeset publish",
27
- "prepublishOnly": "bun run build"
27
+ "version": "changeset version && bun scripts/sync-version.ts",
28
+ "release": "npm run build && changeset publish",
29
+ "prepublishOnly": "npm run build:clean"
28
30
  },
29
31
  "dependencies": {
30
32
  "@modelcontextprotocol/sdk": "1.18.2",
@@ -32,7 +34,7 @@
32
34
  "cors": "^2.8.5",
33
35
  "express": "^5.1.0",
34
36
  "papaparse": "^5.5.3",
35
- "sunsama-api": "0.11.2",
37
+ "sunsama-api": "0.12.1",
36
38
  "zod": "3.24.4"
37
39
  },
38
40
  "devDependencies": {
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * Syncs the version from package.json to src/constants.ts
4
+ * Run automatically as part of `bun run version`
5
+ */
6
+
7
+ import { readFileSync, writeFileSync } from "fs";
8
+ import { join } from "path";
9
+
10
+ const ROOT_DIR = join(import.meta.dirname, "..");
11
+ const PACKAGE_JSON_PATH = join(ROOT_DIR, "package.json");
12
+ const CONSTANTS_PATH = join(ROOT_DIR, "src", "constants.ts");
13
+
14
+ // Read version from package.json
15
+ const packageJson = JSON.parse(readFileSync(PACKAGE_JSON_PATH, "utf-8"));
16
+ const version = packageJson.version;
17
+
18
+ // Read constants.ts
19
+ let constantsContent = readFileSync(CONSTANTS_PATH, "utf-8");
20
+
21
+ // Replace VERSION value
22
+ const versionRegex = /export const VERSION = "[^"]+";/;
23
+ const newVersionLine = `export const VERSION = "${version}";`;
24
+
25
+ if (!versionRegex.test(constantsContent)) {
26
+ console.error("Could not find VERSION export in constants.ts");
27
+ process.exit(1);
28
+ }
29
+
30
+ constantsContent = constantsContent.replace(versionRegex, newVersionLine);
31
+
32
+ // Write back
33
+ writeFileSync(CONSTANTS_PATH, constantsContent);
34
+
35
+ console.log(`Synced VERSION to ${version} in src/constants.ts`);
package/smithery.yaml ADDED
@@ -0,0 +1,9 @@
1
+ runtime: "container"
2
+ startCommand:
3
+ type: "http"
4
+ build:
5
+ dockerfile: "Dockerfile"
6
+ dockerBuildPath: "."
7
+ env:
8
+ TRANSPORT_MODE: "http"
9
+ PORT: "3000"
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Application constants
3
+ *
4
+ * VERSION is automatically synced from package.json by scripts/sync-version.ts
5
+ * when running `bun run version`
6
+ */
7
+
8
+ export const VERSION = "0.16.1";
9
+ export const SERVER_NAME = "Sunsama API Server";
10
+ export const PACKAGE_NAME = "mcp-sunsama";
package/src/main.ts CHANGED
@@ -5,12 +5,13 @@ import { setupStdioTransport } from "./transports/stdio.js";
5
5
  import { setupHttpTransport } from "./transports/http.js";
6
6
  import { allTools } from "./tools/index.js";
7
7
  import { apiDocumentationResource } from "./resources/index.js";
8
+ import { VERSION, SERVER_NAME } from "./constants.js";
8
9
 
9
10
  // Async IIFE for top-level await and error handling
10
11
  (async () => {
11
12
  const server = new McpServer({
12
- name: "Sunsama API Server",
13
- version: "0.15.4",
13
+ name: SERVER_NAME,
14
+ version: VERSION,
14
15
  instructions: `
15
16
  This MCP server provides access to the Sunsama API for task and project management.
16
17
 
package/src/schemas.ts CHANGED
@@ -59,6 +59,50 @@ export const getUserSchema = z.object({});
59
59
  // Get streams parameters (no parameters needed, uses cached group ID)
60
60
  export const getStreamsSchema = z.object({});
61
61
 
62
+ /**
63
+ * Task Integration Schemas
64
+ */
65
+
66
+ // GitHub integration identifier schema
67
+ const githubIntegrationIdentifierSchema = z.object({
68
+ id: z.string().describe("GitHub issue or PR ID"),
69
+ repositoryOwnerLogin: z.string().describe("GitHub repository owner login"),
70
+ repositoryName: z.string().describe("GitHub repository name"),
71
+ number: z.number().int().describe("GitHub issue or PR number"),
72
+ type: z.enum(["Issue", "PullRequest"]).describe("Type of GitHub item"),
73
+ url: z.string().url().describe("URL to the GitHub issue or PR"),
74
+ __typename: z.literal("TaskGithubIntegrationIdentifier"),
75
+ });
76
+
77
+ // GitHub integration schema
78
+ const githubIntegrationSchema = z.object({
79
+ service: z.literal("github"),
80
+ identifier: githubIntegrationIdentifierSchema,
81
+ __typename: z.literal("TaskGithubIntegration"),
82
+ });
83
+
84
+ // Gmail integration identifier schema
85
+ const gmailIntegrationIdentifierSchema = z.object({
86
+ id: z.string().describe("Gmail message ID"),
87
+ messageId: z.string().describe("Gmail message ID (duplicate of id)"),
88
+ accountId: z.string().describe("Gmail account ID"),
89
+ url: z.string().url().describe("URL to the Gmail message"),
90
+ __typename: z.literal("TaskGmailIntegrationIdentifier"),
91
+ });
92
+
93
+ // Gmail integration schema
94
+ const gmailIntegrationSchema = z.object({
95
+ service: z.literal("gmail"),
96
+ identifier: gmailIntegrationIdentifierSchema,
97
+ __typename: z.literal("TaskGmailIntegration"),
98
+ });
99
+
100
+ // Union schema for all task integrations
101
+ const taskIntegrationSchema = z.discriminatedUnion("service", [
102
+ githubIntegrationSchema,
103
+ gmailIntegrationSchema,
104
+ ]);
105
+
62
106
  /**
63
107
  * Task Mutation Operation Schemas
64
108
  */
@@ -83,6 +127,9 @@ export const createTaskSchema = z.object({
83
127
  taskId: z.string().optional().describe(
84
128
  "Custom task ID (auto-generated if not provided)",
85
129
  ),
130
+ integration: taskIntegrationSchema.optional().describe(
131
+ "Integration information for linking task to external services (GitHub, Gmail, etc.)",
132
+ ),
86
133
  });
87
134
 
88
135
  // Update task complete parameters
@@ -153,7 +200,9 @@ export const updateTaskPlannedTimeSchema = z.object({
153
200
  ),
154
201
  });
155
202
 
156
- // Update task notes parameters with XOR content validation
203
+ // Update task notes parameters
204
+ // Note: XOR validation between html/markdown is done in the tool execute function
205
+ // to keep the schema as a plain ZodObject (required for MCP SDK compatibility)
157
206
  export const updateTaskNotesSchema = z.object({
158
207
  taskId: z.string().min(1, "Task ID is required").describe(
159
208
  "The ID of the task to update notes for",
@@ -167,18 +216,7 @@ export const updateTaskNotesSchema = z.object({
167
216
  limitResponsePayload: z.boolean().optional().describe(
168
217
  "Whether to limit the response payload size (defaults to true)",
169
218
  ),
170
- }).refine(
171
- (data) => {
172
- // Exactly one of html or markdown must be provided
173
- const hasHtml = data.html !== undefined;
174
- const hasMarkdown = data.markdown !== undefined;
175
- return hasHtml !== hasMarkdown; // XOR: exactly one must be true
176
- },
177
- {
178
- message: "Exactly one of 'html' or 'markdown' must be provided",
179
- path: [], // This will show the error at the root level
180
- },
181
- );
219
+ });
182
220
 
183
221
  // Update task due date parameters
184
222
  export const updateTaskDueDateSchema = z.object({
@@ -130,6 +130,7 @@ export const createTaskTool = withTransportClient({
130
130
  snoozeUntil,
131
131
  private: isPrivate,
132
132
  taskId,
133
+ integration,
133
134
  }: CreateTaskInput,
134
135
  context: ToolContext,
135
136
  ) => {
@@ -141,6 +142,7 @@ export const createTaskTool = withTransportClient({
141
142
  if (snoozeUntil) options.snoozeUntil = snoozeUntil;
142
143
  if (isPrivate !== undefined) options.private = isPrivate;
143
144
  if (taskId) options.taskId = taskId;
145
+ if (integration) options.integration = integration;
144
146
 
145
147
  const result = await context.client.createTask(text, options);
146
148
 
@@ -293,6 +295,13 @@ export const updateTaskNotesTool = withTransportClient({
293
295
  { taskId, html, markdown, limitResponsePayload }: UpdateTaskNotesInput,
294
296
  context: ToolContext,
295
297
  ) => {
298
+ // XOR validation: exactly one of html or markdown must be provided
299
+ const hasHtml = html !== undefined;
300
+ const hasMarkdown = markdown !== undefined;
301
+ if (hasHtml === hasMarkdown) {
302
+ throw new Error("Exactly one of 'html' or 'markdown' must be provided");
303
+ }
304
+
296
305
  const content = html
297
306
  ? { type: "html" as const, value: html }
298
307
  : { type: "markdown" as const, value: markdown! };
@@ -1,19 +1,20 @@
1
- import express from "express";
2
- import cors from "cors";
3
- import { randomUUID } from "node:crypto";
4
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
5
2
  import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
6
3
  import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
4
+ import cors from "cors";
5
+ import express from "express";
6
+ import { randomUUID } from "node:crypto";
7
7
  import {
8
8
  authenticateHttpRequest,
9
+ cleanupAllClients,
9
10
  startClientCacheCleanup,
10
11
  stopClientCacheCleanup,
11
- cleanupAllClients,
12
12
  } from "../auth/http.js";
13
- import type { TransportConfig } from "../config/transport.js";
14
13
  import type { SessionData } from "../auth/types.js";
15
- import { SessionManager } from "../session/session-manager.js";
16
14
  import { getSessionConfig } from "../config/session-config.js";
15
+ import type { TransportConfig } from "../config/transport.js";
16
+ import { PACKAGE_NAME, VERSION } from "../constants.js";
17
+ import { SessionManager } from "../session/session-manager.js";
17
18
 
18
19
  // Unified session management
19
20
  export const sessionManager = new SessionManager();
@@ -69,13 +70,13 @@ export async function setupHttpTransport(
69
70
  })
70
71
  );
71
72
 
72
- app.use(express.json({ limit: "4mb" }));
73
+ app.use(express.json({limit: "4mb"}));
73
74
 
74
75
  // Health check endpoint
75
76
  app.get("/", (req, res) => {
76
77
  res.json({
77
- name: "mcp-sunsama",
78
- version: "0.15.0",
78
+ name: PACKAGE_NAME,
79
+ version: VERSION,
79
80
  transport: "http",
80
81
  activeSessions: sessionManager.getSessionCount(),
81
82
  });
@@ -248,7 +249,7 @@ export async function setupHttpTransport(
248
249
  }
249
250
  });
250
251
 
251
- const { port } = config.httpStream;
252
+ const {port} = config.httpStream;
252
253
 
253
254
  // Start cleanup timers
254
255
  startClientCacheCleanup();
package/tsconfig.json CHANGED
@@ -32,6 +32,7 @@
32
32
  "exclude": [
33
33
  "dist",
34
34
  "node_modules",
35
- "__tests__"
35
+ "__tests__",
36
+ "scripts"
36
37
  ]
37
38
  }