Skip to content

Commit 1e11f26

Browse files
vscarpenterclaude
andauthored
fix: Critical bug fixes for write operations (v0.4.1-v0.4.7) (#48)
This PR includes 7 critical bug fixes discovered through end-to-end testing of write operations, plus comprehensive documentation updates. ## Bug Fixes ### v0.4.1 - Push Payload Structure - Fixed Worker API payload structure mismatch - Changed `tasks` → `operations` array - Changed `vectorClock` → `clientVectorClock` - Added `type` field to all operations - Changed `id` → `taskId` - Impact: Write operations were 100% non-functional due to 400 errors ### v0.4.2 - JWT Schema Mismatch - Fixed JWT payload schema to match Worker - Changed `user_id` → `sub` (RFC 7519 standard) - Changed `device_id` → `deviceId` (camelCase) - Added `email` and `jti` fields - Added `getUserIdFromToken()` helper - Impact: JWT parsing failed preventing all operations ### v0.4.3 - Missing Checksum - Added SHA-256 checksum calculation for write operations - Added `hash()` method to CryptoManager - Worker requires checksum but schema marked optional - Impact: Tasks silently rejected by Worker (appeared successful) ### v0.4.4 - Rejection Checking - Added validation of Worker's `rejected` array - Tasks could be rejected with HTTP 200 OK - Now throws detailed errors with rejection reasons - Impact: Silent failures without error messages ### v0.4.5 - Field Name Mismatches - Changed `quadrantId` → `quadrant` (frontend uses 'quadrant') - Changed `createdAt: number` → `createdAt: string` (ISO) - Changed `updatedAt: number` → `updatedAt: string` (ISO) - Renamed `deriveQuadrantId()` → `deriveQuadrant()` - Impact: Zod validation errors in webapp ("unrecognized key 'quadrantId'") ### v0.4.6 - Type Mismatches - Changed `dueDate: number | null` → `dueDate?: string` (optional ISO) - Changed `subtasks[].text` → `subtasks[].title` - Added `completedAt?: string` field - Added `vectorClock?: Record<string, number>` field - Impact: "Expected string, received null" errors for dueDate ### v0.4.7 - MCP Tool Schemas - Fixed MCP tool input schemas to match internal types - Updated `dueDate` from `type: 'number'` → `type: 'string'` - Updated subtasks from `text` → `title` field - Impact: Claude Desktop sent wrong data types ## Documentation Updates - Updated README to reflect v0.4.7 production-ready status - Fixed all schema examples (quadrant, subtasks.title, ISO datetimes) - Updated tool documentation with correct parameter types - Added comprehensive bug fix history to README - Updated status section with all 7 bug fixes ## Testing Results All write operations tested end-to-end and working: - ✅ Create task (simple) - ✅ Create task with due date - ✅ Create task with subtasks - ✅ Update task - ✅ Complete task - ✅ Delete task ## Files Changed - CHANGELOG.md - Full bug fix history - README.md - Updated docs and examples - package.json - Version 0.4.7 - src/index.ts - MCP tool schemas, version - src/tools.ts - Schema interfaces (quadrant, dueDate, subtasks) - src/write-ops.ts - All write operation types - src/analytics.ts - Date handling for ISO strings - src/crypto.ts - Added hash() method - src/jwt.ts - Fixed JWT payload schema 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude <noreply@anthropic.com>
1 parent 54945fb commit 1e11f26

File tree

11 files changed

+523
-89
lines changed

11 files changed

+523
-89
lines changed

packages/mcp-server/CHANGELOG.md

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,119 @@ All notable changes to the GSD MCP Server will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [0.4.7] - 2025-10-27 🐛
9+
10+
### Fixed
11+
- **CRITICAL**: Fixed MCP tool input schemas to match internal types
12+
- Changed `dueDate` schema from `type: 'number'``type: 'string'` in all tools
13+
- Changed subtasks schema from `text` field → `title` field in all tools
14+
- **Impact**: v0.4.6 MCP tools accepted wrong input types, causing validation errors in webapp
15+
16+
### Technical Details
17+
- Updated `create_task` tool input schema (line 245-265)
18+
- Updated `update_task` tool input schema (line 307-328)
19+
- Updated `bulk_update_tasks` tool input schema (line 420-423)
20+
- MCP tools now correctly describe ISO 8601 datetime strings for dueDate
21+
- MCP tools now correctly describe subtask.title instead of subtask.text
22+
- Claude Desktop will now send correct data types when calling tools
23+
24+
### Root Cause
25+
- Internal types (CreateTaskInput, UpdateTaskInput) were updated in v0.4.6
26+
- MCP tool schemas in src/index.ts were not updated to match
27+
- Claude Desktop used tool schemas to construct API calls
28+
- Resulted in type mismatch: Claude sent numbers, code expected strings
29+
30+
## [0.4.6] - 2025-10-26 🐛
31+
32+
### Fixed
33+
- **CRITICAL**: Fixed additional schema mismatches preventing task sync
34+
- Changed `dueDate: number | null``dueDate?: string` (optional ISO datetime)
35+
- Changed `subtasks[].text``subtasks[].title` (frontend uses 'title')
36+
- **Impact**: v0.4.5 tasks failed with "Expected string, received null" error on dueDate field
37+
- Added missing optional fields:
38+
- `completedAt?: string` - ISO datetime when task was completed
39+
- `vectorClock?: Record<string, number>` - For sync conflict resolution
40+
- Updated all write operations to handle optional fields correctly:
41+
- `dueDate` only included when set (not null)
42+
- `completedAt` set automatically when marking task complete
43+
- `vectorClock` initialized with empty object
44+
- Fixed analytics date sorting to handle ISO datetime strings
45+
46+
### Technical Details
47+
- Frontend schema expects `dueDate: z.string().datetime().optional()` (can be undefined, NOT null)
48+
- Frontend subtask schema uses `title`, not `text` (line 19 of lib/schema.ts)
49+
- Updated CreateTaskInput, UpdateTaskInput, and BulkOperation types
50+
- Fixed searchTasks to search subtask.title instead of subtask.text
51+
- Updated date comparisons in analytics to parse ISO strings before sorting
52+
53+
## [0.4.5] - 2025-10-26 🐛
54+
55+
### Fixed
56+
- **CRITICAL**: Fixed task schema to match frontend expectations
57+
- Changed `quadrantId``quadrant` (frontend schema uses 'quadrant')
58+
- Changed `createdAt` from number → ISO string datetime
59+
- Changed `updatedAt` from number → ISO string datetime
60+
- **Impact**: v0.4.0-0.4.4 tasks created by MCP failed Zod validation in webapp causing "unrecognized key 'quadrantId'" error
61+
62+
### Technical Details
63+
- Updated `DecryptedTask` interface in `src/tools.ts`
64+
- Updated all write operations to use `quadrant` field name
65+
- Renamed `deriveQuadrantId()``deriveQuadrant()`
66+
- Changed timestamp generation from `Date.now()``new Date().toISOString()`
67+
- Frontend expects ISO 8601 datetime strings, not Unix timestamps
68+
- Frontend schema in `lib/schema.ts` uses `quadrant: quadrantIdSchema`
69+
70+
## [0.4.4] - 2025-10-26 🐛
71+
72+
### Fixed
73+
- **CRITICAL**: Added validation of Worker push response rejected array
74+
- MCP server was not checking if Worker rejected operations
75+
- Only checked HTTP status (200 OK) and conflicts array
76+
- Worker can reject operations and still return 200 OK with rejected array
77+
- Now throws detailed error if any operations are rejected
78+
- **Impact**: v0.4.0-0.4.3 appeared to succeed but tasks were silently rejected
79+
80+
### Technical Details
81+
- Updated `pushToSync()` to parse full `PushResponse` structure
82+
- Added check for `rejected` array in Worker response
83+
- Throws error with detailed rejection reasons (taskId, reason, details)
84+
- Now properly validates that `accepted` array contains the task IDs
85+
- This will surface the actual rejection reason from Worker
86+
87+
## [0.4.3] - 2025-10-26 🐛
88+
89+
### Fixed
90+
- **CRITICAL**: Added missing checksum calculation for write operations
91+
- Worker requires SHA-256 checksum of plaintext JSON for create/update operations
92+
- Added `hash()` method to `CryptoManager` using Web Crypto API
93+
- Updated all write operations to calculate and include checksum
94+
- **Impact**: Tasks created without checksum were silently rejected by Worker (appeared successful but not stored)
95+
96+
### Technical Details
97+
- Added `CryptoManager.hash()` method using `webcrypto.subtle.digest('SHA-256')`
98+
- Updated `createTask()` to calculate checksum before push
99+
- Updated `updateTask()` to calculate checksum before push
100+
- Updated `bulkUpdateTasks()` to calculate checksums for all operations
101+
- Checksum is SHA-256 hash of plaintext JSON (before encryption)
102+
- Worker validates checksum on line 125 of `worker/src/handlers/sync.ts`
103+
- Schema says checksum is optional, but Worker code requires it for create/update
104+
105+
## [0.4.2] - 2025-10-26 🐛
106+
107+
### Fixed
108+
- **CRITICAL**: Fixed JWT payload schema mismatch between MCP server and Worker
109+
- Changed `user_id``sub` (JWT standard subject field)
110+
- Changed `device_id``deviceId` (camelCase to match Worker)
111+
- Added `email` and `jti` fields to match Worker's JWT structure
112+
- Added `getUserIdFromToken()` helper function
113+
- **Impact**: JWT parsing was failing with "user_id and device_id are missing" error, preventing all operations
114+
115+
### Technical Details
116+
- Updated `jwtPayloadSchema` in `src/jwt.ts` to match `worker/src/utils/jwt.ts`
117+
- Worker generates JWT with standard `sub` field (RFC 7519), not custom `user_id`
118+
- Worker uses camelCase `deviceId`, not snake_case `device_id`
119+
- MCP server now correctly parses tokens from actual Worker OAuth flow
120+
8121
## [0.4.1] - 2025-10-26 🐛
9122

10123
### Fixed

packages/mcp-server/README.md

Lines changed: 36 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
[![npm version](https://badge.fury.io/js/gsd-mcp-server.svg)](https://www.npmjs.com/package/gsd-mcp-server)
44
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
55

6-
Model Context Protocol (MCP) server for GSD Task Manager. Provides read-only access to your synced tasks through Claude Desktop and other MCP-compatible AI assistants.
6+
Model Context Protocol (MCP) server for GSD Task Manager. Provides **full task management** capabilities including create, read, update, and delete operations through Claude Desktop and other MCP-compatible AI assistants. All operations maintain end-to-end encryption.
77

88
## Quick Start
99

@@ -75,12 +75,7 @@ See [Installation](#installation) section below for detailed setup instructions.
7575
- ✅ Filter by quadrant, completion status, tags
7676
- ✅ Get individual task details
7777
- 🔒 Privacy-first: Requires user-provided encryption passphrase
78-
- 🔒 Read-only: Cannot modify or create tasks
79-
80-
**Planned** (Future v0.4.0+)
81-
- Write operations (create, update, delete tasks)
82-
- AI-powered task suggestions
83-
- Bulk operations support
78+
- ✅ Full CRUD operations: Create, read, update, delete tasks (v0.4.0+)
8479

8580
## Prerequisites
8681

@@ -366,18 +361,19 @@ List all decrypted tasks with optional filtering. **Requires `GSD_ENCRYPTION_PAS
366361
"description": "Complete Q4 financial analysis",
367362
"urgent": true,
368363
"important": true,
369-
"quadrantId": "urgent-important",
364+
"quadrant": "urgent-important",
370365
"completed": false,
371-
"dueDate": 1735948800000,
366+
"dueDate": "2025-01-03T17:00:00.000Z",
372367
"tags": ["#work", "#finance"],
373368
"subtasks": [
374-
{ "id": "sub-1", "text": "Gather data", "completed": true },
375-
{ "id": "sub-2", "text": "Write analysis", "completed": false }
369+
{ "id": "sub-1", "title": "Gather data", "completed": true },
370+
{ "id": "sub-2", "title": "Write analysis", "completed": false }
376371
],
377372
"recurrence": "none",
378373
"dependencies": [],
379-
"createdAt": 1735171200000,
380-
"updatedAt": 1735257600000
374+
"createdAt": "2024-12-26T00:00:00.000Z",
375+
"updatedAt": "2024-12-27T00:00:00.000Z",
376+
"vectorClock": {}
381377
}
382378
]
383379
```
@@ -539,9 +535,9 @@ Create a new task with natural language input. **Requires `GSD_ENCRYPTION_PASSPH
539535
- `urgent` (required): Is this task urgent? (time-sensitive)
540536
- `important` (required): Is this task important? (high-value, strategic)
541537
- `description` (optional): Task description
542-
- `dueDate` (optional): Due date as Unix timestamp (milliseconds)
538+
- `dueDate` (optional): Due date as ISO 8601 datetime string (e.g., `"2025-10-27T17:00:00.000Z"`)
543539
- `tags` (optional): Array of tags (e.g., `["#work", "#project-alpha"]`)
544-
- `subtasks` (optional): Array of subtask objects `{text, completed}`
540+
- `subtasks` (optional): Array of subtask objects `{title, completed}`
545541
- `recurrence` (optional): `'none'` | `'daily'` | `'weekly'` | `'monthly'`
546542
- `dependencies` (optional): Array of task IDs that must be completed first
547543

@@ -566,9 +562,9 @@ Update an existing task. All fields except ID are optional. **Requires `GSD_ENCR
566562
- `description` (optional): New description
567563
- `urgent` (optional): Change urgency (moves between quadrants)
568564
- `important` (optional): Change importance (moves between quadrants)
569-
- `dueDate` (optional): New due date (null to clear)
565+
- `dueDate` (optional): New due date as ISO 8601 datetime string (empty string to clear)
570566
- `tags` (optional): Replace all tags
571-
- `subtasks` (optional): Replace all subtasks
567+
- `subtasks` (optional): Replace all subtasks (objects with `{id, title, completed}`)
572568
- `recurrence` (optional): Change recurrence pattern
573569
- `dependencies` (optional): Replace all dependencies
574570
- `completed` (optional): Mark as complete/incomplete
@@ -627,7 +623,7 @@ Update multiple tasks at once. Limited to 50 tasks per operation for safety. **R
627623
- `type: 'remove_tags'` - Remove tags from all tasks
628624
- `tags`: string[]
629625
- `type: 'set_due_date'` - Set due date for all tasks
630-
- `dueDate`: number | null
626+
- `dueDate`: ISO 8601 datetime string (empty string to clear)
631627
- `type: 'delete'` - Delete all tasks
632628
- `maxTasks` (optional): Safety limit (default: 50)
633629

@@ -753,21 +749,15 @@ npm publish --access public --otp=YOUR_CODE
753749

754750
## Future Enhancements
755751

756-
**Write Operations** (v0.4.0)
757-
- Create new tasks via natural language
758-
- Update existing tasks (title, description, quadrant, etc.)
759-
- Complete/uncomplete tasks
760-
- Delete tasks
761-
- Conflict resolution for concurrent edits
762-
- Batch operations support
763-
764752
**Advanced Features** (v0.5.0+)
765753
- AI-powered task suggestions based on patterns
766754
- Priority recommendations using AI
767755
- Deadline predictions
768756
- Historical trend analysis (7/30/90 day views)
769757
- Cross-integration with calendar/email (MCP chaining)
770758
- Custom analytics queries
759+
- Conflict resolution UI for concurrent edits
760+
- Task templates and quick creation workflows
771761

772762
## Architecture
773763

@@ -827,21 +817,34 @@ MIT - Same as GSD Task Manager
827817

828818
---
829819

830-
**Status**: v0.4.0 (Write Operations) 🔥
831-
**New in v0.4.0**:
820+
**Status**: v0.4.7 (Production Ready) ✅🔥
821+
822+
**Current Release (v0.4.7)**:
832823
- ✍️ **Full task management** - Create, update, delete tasks
833-
- 🔄 **Bulk operations** - Update up to 50 tasks at once
824+
- 🔄 **Bulk operations** - Update up to 50 tasks at once (complete, move, tag, delete)
834825
- 🔐 **Encrypted writes** - All changes encrypted before sync
835826
- 🛡️ **Safety features** - Bulk limits, validation, clear errors
836827
- 📊 **18 total MCP tools** (13 read + 5 write)
837-
838-
**Previous Releases**:
828+
-**Production tested** - All write operations verified end-to-end
829+
- 🐛 **Bug fixes** - 7 critical schema and sync issues resolved (v0.4.1-v0.4.7)
830+
831+
**Bug Fixes (v0.4.1-v0.4.7)**:
832+
- v0.4.1: Fixed Worker API payload structure
833+
- v0.4.2: Fixed JWT token schema (sub, deviceId)
834+
- v0.4.3: Added SHA-256 checksum calculation
835+
- v0.4.4: Added Worker rejection array checking
836+
- v0.4.5: Fixed field names (quadrant, timestamps)
837+
- v0.4.6: Fixed type mismatches (dueDate, subtasks.title)
838+
- v0.4.7: Fixed MCP tool input schemas
839+
840+
**Previous Feature Releases**:
841+
- v0.4.0 - Write operations (create, update, delete)
839842
- v0.3.2 - Built-in prompts, help tool
840843
- v0.3.0 - Interactive setup, analytics, validation
841844
- v0.2.0 - Decrypted task access
842845
- v0.1.0 - Metadata-only access
843846

844847
**Privacy**: Opt-in decryption with local passphrase
845848
**Security**: E2E encryption maintained, zero-knowledge server
846-
**Capabilities**: Full task management (create, read, update, delete)
847-
**Deployment**: Published to npm ✅ | Ready for production
849+
**Capabilities**: Full CRUD task management with natural language interface
850+
**Deployment**: Published to npm ✅ | Production ready ✅ | All tests passed

0 commit comments

Comments
 (0)