|
| 1 | +# Bidirectional Synchronization: MCP GitHub Project Manager |
| 2 | + |
| 3 | +This document details the bidirectional synchronization mechanism between the MCP GitHub Project Manager and GitHub's API. |
| 4 | + |
| 5 | +## 1. Real-time Task Update Flow |
| 6 | + |
| 7 | +The system uses a combination of webhooks and periodic synchronization to maintain real-time updates: |
| 8 | + |
| 9 | +```typescript |
| 10 | +private async handleProjectsV2ItemEvent(webhook: WebhookEvent): Promise<ResourceEvent[]> { |
| 11 | + const { action, projects_v2_item: item } = webhook.payload; |
| 12 | + |
| 13 | + const events: ResourceEvent[] = []; |
| 14 | + |
| 15 | + // Handle the item itself (could be an issue or pull request) |
| 16 | + if (item.content_type === 'Issue' && item.content_node_id) { |
| 17 | + const eventType = this.mapActionToEventType(action); |
| 18 | + if (eventType) { |
| 19 | + events.push({ |
| 20 | + id: `${webhook.id}-issue-${item.content_node_id}`, |
| 21 | + type: eventType, |
| 22 | + resourceType: ResourceType.ISSUE, |
| 23 | + resourceId: item.content_node_id, |
| 24 | + // ...other properties |
| 25 | + }); |
| 26 | + } |
| 27 | + } |
| 28 | + |
| 29 | + return events; |
| 30 | +} |
| 31 | +``` |
| 32 | + |
| 33 | +The flow works as follows: |
| 34 | +1. GitHub sends webhook events when tasks (issues/PRs) are updated |
| 35 | +2. The `GitHubWebhookHandler` processes these events and converts them to standardized `ResourceEvent` objects |
| 36 | +3. These events are then propagated through the system to update local state |
| 37 | +4. For outgoing changes, the MCP server uses GitHub's GraphQL API to push updates |
| 38 | + |
| 39 | +## 2. Detecting Human Team Member Changes |
| 40 | + |
| 41 | +Changes made by team members in GitHub Projects are detected through: |
| 42 | + |
| 43 | +```typescript |
| 44 | +private async syncResourceTypeWithMetadata( |
| 45 | + type: ResourceType, |
| 46 | + metadata: SyncMetadata[] |
| 47 | +): Promise<{ synced: number; skipped: number }> { |
| 48 | + // Check which resources need syncing |
| 49 | + const resourcesNeedingSync = await this.checkResourceChanges(metadata); |
| 50 | + |
| 51 | + this.logger.info(`${type}: ${resourcesNeedingSync.length} resources need syncing out of ${metadata.length} total`); |
| 52 | + |
| 53 | + // Sync resources that need updating |
| 54 | + for (const resourceId of resourcesNeedingSync) { |
| 55 | + try { |
| 56 | + await this.syncSingleResource(type, resourceId); |
| 57 | + synced++; |
| 58 | + } catch (error) { |
| 59 | + this.logger.warn(`Failed to sync ${type} ${resourceId}:`, error); |
| 60 | + // Continue with other resources |
| 61 | + } |
| 62 | + } |
| 63 | + // ... |
| 64 | +} |
| 65 | +``` |
| 66 | + |
| 67 | +The system: |
| 68 | +1. Maintains metadata about each resource including last modified timestamps |
| 69 | +2. Periodically checks for changes using the `checkResourceChanges` method |
| 70 | +3. Uses ETag/version tracking to detect changes efficiently |
| 71 | +4. Synchronizes only resources that have changed since last sync |
| 72 | + |
| 73 | +## 3. Progress Tracking and Status Updates |
| 74 | + |
| 75 | +When developers update task status in GitHub, the system: |
| 76 | + |
| 77 | +1. Receives webhook notifications for status changes |
| 78 | +2. Updates the local cache with new status information |
| 79 | +3. Propagates these changes to any subscribed clients |
| 80 | +4. Updates progress metrics based on task status changes |
| 81 | + |
| 82 | +The implementation leverages the event system to track these changes in real-time. |
| 83 | + |
| 84 | +## 4. Components for Event Handling and Synchronization |
| 85 | + |
| 86 | +The key components responsible for handling events and synchronization are: |
| 87 | + |
| 88 | +1. **GitHubWebhookHandler**: Processes incoming webhook events from GitHub |
| 89 | + - Converts GitHub-specific events to standardized resource events |
| 90 | + - Handles different event types (projects, issues, PRs, etc.) |
| 91 | + |
| 92 | +2. **GitHubStateSyncService**: Manages state synchronization |
| 93 | + - Performs initial sync on startup |
| 94 | + - Handles periodic syncs for specific resource types |
| 95 | + - Maintains metadata for efficient change detection |
| 96 | + |
| 97 | +3. **ResourceCache**: Stores synchronized resources |
| 98 | + - Provides type-safe access to resources |
| 99 | + - Tracks resource metadata for change detection |
| 100 | + |
| 101 | +4. **EventSubscriptionManager**: Manages client subscriptions to events |
| 102 | + - Allows filtering by resource type and event type |
| 103 | + - Delivers events to subscribed clients |
| 104 | + |
| 105 | +Conflict resolution uses optimistic locking with version checks: |
| 106 | + |
| 107 | +```typescript |
| 108 | +// Example field update with retry |
| 109 | +async function updateFieldValue( |
| 110 | + projectId: string, |
| 111 | + itemId: string, |
| 112 | + fieldId: string, |
| 113 | + value: any |
| 114 | +): Promise<void> { |
| 115 | + await retryManager.executeWithRetry(async () => { |
| 116 | + const lock = await lockManager.acquireLock(itemId); |
| 117 | + try { |
| 118 | + await fieldManager.validateValue(fieldId, value); |
| 119 | + await projectRepo.updateFieldValue(projectId, itemId, fieldId, value); |
| 120 | + } finally { |
| 121 | + await lockManager.releaseLock(itemId, lock.id); |
| 122 | + } |
| 123 | + }); |
| 124 | +} |
| 125 | +``` |
| 126 | + |
| 127 | +## 5. Recalibrating Task Estimates and Project Timelines |
| 128 | + |
| 129 | +The system recalibrates task estimates and project timelines through: |
| 130 | + |
| 131 | +1. **AI-powered analysis**: The system includes AI tools that can analyze task complexity and adjust estimates |
| 132 | +2. **Event-based triggers**: When tasks are updated, the system can trigger re-estimation |
| 133 | +3. **Progressive response**: Updates are streamed to clients as they occur |
| 134 | + |
| 135 | +``` |
| 136 | +# 3. Get next task recommendations |
| 137 | +get_next_task({ |
| 138 | + "sprintCapacity": 40, |
| 139 | + "teamSkills": ["react", "node.js", "typescript", "python"], |
| 140 | + "maxComplexity": 7, |
| 141 | + "includeAnalysis": true, |
| 142 | + "excludeBlocked": true |
| 143 | +}) |
| 144 | +``` |
| 145 | + |
| 146 | +The AI features can analyze task progress and provide updated recommendations as the project evolves. |
| 147 | + |
| 148 | +## Architecture Diagram |
| 149 | + |
| 150 | +``` |
| 151 | +┌─────────────────┐ ┌─────────────────┐ |
| 152 | +│ GitHub API │◄────────┤ Webhook Handler │ |
| 153 | +│ (Projects v2) │ └────────┬────────┘ |
| 154 | +└────────┬────────┘ │ |
| 155 | + │ ▼ |
| 156 | + │ ┌─────────────────┐ |
| 157 | + │ │ Event System │ |
| 158 | + │ │ - Subscription │ |
| 159 | + │ │ - Event Store │ |
| 160 | + │ └────────┬────────┘ |
| 161 | + │ │ |
| 162 | + ▼ ▼ |
| 163 | +┌─────────────────┐ ┌─────────────────┐ |
| 164 | +│ GitHub Repos │◄────────┤ Resource Cache │ |
| 165 | +│ - Project │ │ - Type Safety │ |
| 166 | +│ - Issue │ │ - Metadata │ |
| 167 | +│ - Milestone │ └────────┬────────┘ |
| 168 | +└────────┬────────┘ │ |
| 169 | + │ ▼ |
| 170 | + │ ┌─────────────────┐ |
| 171 | + │ │ Sync Service │ |
| 172 | + ▼ │ - Change Detect │ |
| 173 | +┌─────────────────┐ │ - Versioning │ |
| 174 | +│ MCP Layer │◄────────┤ - Persistence │ |
| 175 | +└─────────────────┘ └─────────────────┘ |
| 176 | +``` |
| 177 | + |
| 178 | +This bidirectional synchronization architecture ensures that changes flow seamlessly between GitHub and the MCP system, maintaining consistency while providing real-time updates to all stakeholders. |
0 commit comments