@vibescope/mcp-server 0.2.1 → 0.2.2

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 (93) hide show
  1. package/README.md +60 -7
  2. package/dist/api-client.d.ts +187 -0
  3. package/dist/api-client.js +48 -0
  4. package/dist/handlers/blockers.js +9 -8
  5. package/dist/handlers/bodies-of-work.js +14 -14
  6. package/dist/handlers/connectors.d.ts +45 -0
  7. package/dist/handlers/connectors.js +183 -0
  8. package/dist/handlers/cost.d.ts +10 -0
  9. package/dist/handlers/cost.js +54 -0
  10. package/dist/handlers/decisions.js +3 -3
  11. package/dist/handlers/deployment.js +35 -19
  12. package/dist/handlers/discovery.d.ts +7 -0
  13. package/dist/handlers/discovery.js +61 -2
  14. package/dist/handlers/fallback.js +5 -4
  15. package/dist/handlers/file-checkouts.d.ts +2 -0
  16. package/dist/handlers/file-checkouts.js +38 -6
  17. package/dist/handlers/findings.js +13 -12
  18. package/dist/handlers/git-issues.js +4 -4
  19. package/dist/handlers/ideas.js +5 -5
  20. package/dist/handlers/index.d.ts +1 -0
  21. package/dist/handlers/index.js +3 -0
  22. package/dist/handlers/milestones.js +5 -5
  23. package/dist/handlers/organizations.js +13 -13
  24. package/dist/handlers/progress.js +2 -2
  25. package/dist/handlers/project.js +6 -6
  26. package/dist/handlers/requests.js +3 -3
  27. package/dist/handlers/session.js +28 -9
  28. package/dist/handlers/sprints.js +17 -17
  29. package/dist/handlers/tasks.d.ts +2 -0
  30. package/dist/handlers/tasks.js +78 -20
  31. package/dist/handlers/types.d.ts +64 -2
  32. package/dist/handlers/types.js +48 -1
  33. package/dist/handlers/validation.js +3 -3
  34. package/dist/index.js +7 -2716
  35. package/dist/token-tracking.d.ts +74 -0
  36. package/dist/token-tracking.js +122 -0
  37. package/dist/tools.js +298 -9
  38. package/dist/utils.d.ts +5 -0
  39. package/dist/utils.js +17 -0
  40. package/docs/TOOLS.md +2053 -0
  41. package/package.json +4 -1
  42. package/scripts/generate-docs.ts +212 -0
  43. package/src/api-client.test.ts +718 -0
  44. package/src/api-client.ts +231 -0
  45. package/src/handlers/__test-setup__.ts +9 -0
  46. package/src/handlers/blockers.test.ts +31 -19
  47. package/src/handlers/blockers.ts +9 -8
  48. package/src/handlers/bodies-of-work.test.ts +55 -32
  49. package/src/handlers/bodies-of-work.ts +14 -14
  50. package/src/handlers/connectors.test.ts +834 -0
  51. package/src/handlers/connectors.ts +229 -0
  52. package/src/handlers/cost.ts +66 -0
  53. package/src/handlers/decisions.test.ts +34 -25
  54. package/src/handlers/decisions.ts +3 -3
  55. package/src/handlers/deployment.ts +39 -19
  56. package/src/handlers/discovery.ts +61 -2
  57. package/src/handlers/fallback.test.ts +26 -22
  58. package/src/handlers/fallback.ts +5 -4
  59. package/src/handlers/file-checkouts.test.ts +242 -49
  60. package/src/handlers/file-checkouts.ts +44 -6
  61. package/src/handlers/findings.test.ts +38 -24
  62. package/src/handlers/findings.ts +13 -12
  63. package/src/handlers/git-issues.test.ts +51 -43
  64. package/src/handlers/git-issues.ts +4 -4
  65. package/src/handlers/ideas.test.ts +28 -23
  66. package/src/handlers/ideas.ts +5 -5
  67. package/src/handlers/index.ts +3 -0
  68. package/src/handlers/milestones.test.ts +33 -28
  69. package/src/handlers/milestones.ts +5 -5
  70. package/src/handlers/organizations.test.ts +104 -83
  71. package/src/handlers/organizations.ts +13 -13
  72. package/src/handlers/progress.test.ts +20 -14
  73. package/src/handlers/progress.ts +2 -2
  74. package/src/handlers/project.test.ts +34 -27
  75. package/src/handlers/project.ts +6 -6
  76. package/src/handlers/requests.test.ts +27 -18
  77. package/src/handlers/requests.ts +3 -3
  78. package/src/handlers/session.test.ts +47 -0
  79. package/src/handlers/session.ts +32 -9
  80. package/src/handlers/sprints.test.ts +71 -50
  81. package/src/handlers/sprints.ts +17 -17
  82. package/src/handlers/tasks.test.ts +77 -15
  83. package/src/handlers/tasks.ts +90 -21
  84. package/src/handlers/tool-categories.test.ts +66 -0
  85. package/src/handlers/types.ts +81 -2
  86. package/src/handlers/validation.test.ts +78 -45
  87. package/src/handlers/validation.ts +3 -3
  88. package/src/index.ts +12 -2732
  89. package/src/token-tracking.test.ts +453 -0
  90. package/src/token-tracking.ts +164 -0
  91. package/src/tools.ts +298 -9
  92. package/src/utils.test.ts +2 -2
  93. package/src/utils.ts +17 -0
package/README.md CHANGED
@@ -88,24 +88,77 @@ claude mcp add vibescope npx @vibescope/mcp-server \
88
88
 
89
89
  ## Available Tools
90
90
 
91
- The MCP server provides these tools for AI agents:
91
+ The MCP server provides **130 tools** for AI agents. Here are the key tools by category:
92
92
 
93
+ ### Session
94
+ | Tool | Description |
95
+ |------|-------------|
96
+ | `start_work_session` | Initialize session, get persona, role, and next task |
97
+ | `end_work_session` | End session and release claimed tasks |
98
+ | `heartbeat` | Keep session active (call every 30-60s) |
99
+ | `get_help` | Get guidance on workflows |
100
+ | `discover_tools` | List tools by category |
101
+ | `get_tool_info` | Get detailed tool documentation |
102
+
103
+ ### Projects
104
+ | Tool | Description |
105
+ |------|-------------|
106
+ | `create_project` | Create a new project |
107
+ | `update_project` | Update project details and git workflow |
108
+ | `get_project_context` | Get full project context |
109
+ | `get_git_workflow` | Get git branching instructions |
110
+ | `query_knowledge_base` | Query aggregated project knowledge |
111
+
112
+ ### Tasks
93
113
  | Tool | Description |
94
114
  |------|-------------|
95
- | `start_work_session` | Initialize a work session for a project |
96
- | `get_project_context` | Get full project context including tasks, blockers, and user updates |
97
115
  | `get_tasks` | List tasks, optionally filtered by status |
98
- | `get_next_task` | Get the highest priority pending task |
116
+ | `get_next_task` | Get highest priority pending task |
99
117
  | `add_task` | Create a new task |
100
118
  | `update_task` | Update task status, progress, or details |
101
119
  | `complete_task` | Mark a task as completed |
120
+ | `add_subtask` | Break down tasks into subtasks |
121
+ | `add_task_reference` | Add reference URL (docs, PRs) |
122
+ | `batch_update_tasks` | Update multiple tasks at once |
123
+
124
+ ### Progress & Context
125
+ | Tool | Description |
126
+ |------|-------------|
102
127
  | `log_progress` | Log a progress update |
103
128
  | `add_blocker` | Flag a blocker needing human input |
104
129
  | `resolve_blocker` | Mark a blocker as resolved |
105
- | `log_decision` | Record an architectural or technical decision |
130
+ | `log_decision` | Record an architectural decision |
106
131
  | `add_idea` | Record an improvement idea |
107
- | `create_project` | Create a new project |
108
- | `update_project` | Update project details |
132
+ | `add_finding` | Record an audit finding |
133
+
134
+ ### Validation & Deployment
135
+ | Tool | Description |
136
+ |------|-------------|
137
+ | `get_tasks_awaiting_validation` | Get tasks needing review |
138
+ | `claim_validation` | Claim a task for review |
139
+ | `validate_task` | Approve or reject work |
140
+ | `request_deployment` | Request a deployment |
141
+ | `check_deployment_status` | Check deployment state |
142
+ | `complete_deployment` | Mark deployment done |
143
+
144
+ ### Collaboration
145
+ | Tool | Description |
146
+ |------|-------------|
147
+ | `add_milestone` | Track progress on complex tasks |
148
+ | `create_body_of_work` | Group tasks into phases |
149
+ | `create_sprint` | Create time-bounded sprints |
150
+ | `checkout_file` | Prevent file conflicts |
151
+ | `get_pending_requests` | Get human requests |
152
+ | `answer_question` | Answer user questions |
153
+
154
+ ### Additional Categories
155
+ - **Organizations**: Create, manage, and share projects with teams
156
+ - **Cost Tracking**: Monitor spending with alerts and summaries
157
+ - **Git Issues**: Track merge conflicts and push failures
158
+ - **Role Management**: Configure agent roles (developer, validator, deployer)
159
+ - **Scheduled Deployments**: Schedule recurring deployments
160
+
161
+ Use `discover_tools` to explore all categories and `get_tool_info` for detailed documentation
109
162
 
110
163
  ## Rate Limits
111
164
 
@@ -69,6 +69,23 @@ export declare class VibescopeApiClient {
69
69
  priority: number;
70
70
  estimated_minutes?: number;
71
71
  } | null;
72
+ pending_requests?: Array<{
73
+ id: string;
74
+ request_type: string;
75
+ message: string;
76
+ created_at: string;
77
+ }>;
78
+ pending_requests_count?: number;
79
+ URGENT_QUESTIONS?: {
80
+ count: number;
81
+ oldest_waiting_minutes: number;
82
+ action_required: string;
83
+ requests: Array<{
84
+ id: string;
85
+ message: string;
86
+ waiting_minutes: number;
87
+ }>;
88
+ };
72
89
  directive?: string;
73
90
  blockers_count?: number;
74
91
  validation_count?: number;
@@ -275,6 +292,7 @@ export declare class VibescopeApiClient {
275
292
  progress_note?: string;
276
293
  estimated_minutes?: number;
277
294
  git_branch?: string;
295
+ worktree_path?: string;
278
296
  session_id?: string;
279
297
  }): Promise<ApiResponse<{
280
298
  success: boolean;
@@ -1057,6 +1075,63 @@ export declare class VibescopeApiClient {
1057
1075
  output_tokens: number;
1058
1076
  }>;
1059
1077
  }>>;
1078
+ getBodyOfWorkCosts(params: {
1079
+ body_of_work_id?: string;
1080
+ project_id?: string;
1081
+ }): Promise<ApiResponse<{
1082
+ bodies_of_work: Array<{
1083
+ body_of_work_id: string;
1084
+ title: string;
1085
+ project_id: string;
1086
+ status: string;
1087
+ task_count: number;
1088
+ total_cost_usd: number;
1089
+ total_tokens: number;
1090
+ pre_phase_cost_usd: number;
1091
+ core_phase_cost_usd: number;
1092
+ post_phase_cost_usd: number;
1093
+ model_breakdown: Record<string, {
1094
+ input: number;
1095
+ output: number;
1096
+ }>;
1097
+ }>;
1098
+ count: number;
1099
+ totals: {
1100
+ total_cost_usd: number;
1101
+ total_tokens: number;
1102
+ total_tasks: number;
1103
+ };
1104
+ }>>;
1105
+ getSprintCosts(params: {
1106
+ sprint_id?: string;
1107
+ project_id?: string;
1108
+ }): Promise<ApiResponse<{
1109
+ sprints: Array<{
1110
+ sprint_id: string;
1111
+ title: string;
1112
+ project_id: string;
1113
+ status: string;
1114
+ sprint_number: number;
1115
+ task_count: number;
1116
+ total_cost_usd: number;
1117
+ total_tokens: number;
1118
+ cost_per_story_point: number | null;
1119
+ committed_points: number;
1120
+ velocity_points: number;
1121
+ model_breakdown: Record<string, {
1122
+ input: number;
1123
+ output: number;
1124
+ }>;
1125
+ }>;
1126
+ count: number;
1127
+ totals: {
1128
+ total_cost_usd: number;
1129
+ total_tokens: number;
1130
+ total_tasks: number;
1131
+ total_velocity_points: number;
1132
+ avg_cost_per_point: number | null;
1133
+ };
1134
+ }>>;
1060
1135
  getTokenUsage(): Promise<ApiResponse<{
1061
1136
  session_tokens: number;
1062
1137
  estimated_cost: number;
@@ -1116,6 +1191,7 @@ export declare class VibescopeApiClient {
1116
1191
  environment?: string;
1117
1192
  version_bump?: string;
1118
1193
  auto_trigger?: boolean;
1194
+ hours_interval?: number;
1119
1195
  notes?: string;
1120
1196
  git_ref?: string;
1121
1197
  }): Promise<ApiResponse<{
@@ -1127,6 +1203,7 @@ export declare class VibescopeApiClient {
1127
1203
  id: string;
1128
1204
  scheduled_at: string;
1129
1205
  schedule_type: string;
1206
+ hours_interval: number;
1130
1207
  environment: string;
1131
1208
  version_bump: string;
1132
1209
  auto_trigger: boolean;
@@ -1140,6 +1217,7 @@ export declare class VibescopeApiClient {
1140
1217
  updateScheduledDeployment(scheduleId: string, updates: {
1141
1218
  scheduled_at?: string;
1142
1219
  schedule_type?: string;
1220
+ hours_interval?: number;
1143
1221
  environment?: string;
1144
1222
  version_bump?: string;
1145
1223
  auto_trigger?: boolean;
@@ -1226,6 +1304,115 @@ export declare class VibescopeApiClient {
1226
1304
  checkout_id: string;
1227
1305
  message: string;
1228
1306
  }>>;
1307
+ getStaleWorktrees(projectId: string): Promise<ApiResponse<{
1308
+ project_id: string;
1309
+ project_name: string;
1310
+ stale_worktrees: Array<{
1311
+ task_id: string;
1312
+ task_title: string;
1313
+ worktree_path: string;
1314
+ git_branch: string | null;
1315
+ status: string;
1316
+ completed_at: string | null;
1317
+ updated_at: string;
1318
+ pr_url: string | null;
1319
+ stale_reason: 'task_finished' | 'potentially_abandoned';
1320
+ }>;
1321
+ count: number;
1322
+ cleanup_instructions: string[] | null;
1323
+ }>>;
1324
+ clearWorktreePath(taskId: string): Promise<ApiResponse<{
1325
+ success: boolean;
1326
+ task_id: string;
1327
+ }>>;
1328
+ getConnectors(projectId: string, params?: {
1329
+ type?: string;
1330
+ status?: string;
1331
+ limit?: number;
1332
+ offset?: number;
1333
+ }): Promise<ApiResponse<{
1334
+ connectors: Array<{
1335
+ id: string;
1336
+ name: string;
1337
+ type: string;
1338
+ description?: string;
1339
+ status: string;
1340
+ events: Record<string, boolean>;
1341
+ events_sent: number;
1342
+ last_triggered_at?: string;
1343
+ last_error?: string;
1344
+ last_error_at?: string;
1345
+ created_at: string;
1346
+ }>;
1347
+ total_count: number;
1348
+ has_more: boolean;
1349
+ }>>;
1350
+ getConnector(connectorId: string): Promise<ApiResponse<{
1351
+ connector: {
1352
+ id: string;
1353
+ name: string;
1354
+ type: string;
1355
+ description?: string;
1356
+ config: Record<string, unknown>;
1357
+ events: Record<string, boolean>;
1358
+ status: string;
1359
+ events_sent: number;
1360
+ last_triggered_at?: string;
1361
+ last_error?: string;
1362
+ last_error_at?: string;
1363
+ created_at: string;
1364
+ };
1365
+ }>>;
1366
+ addConnector(projectId: string, params: {
1367
+ name: string;
1368
+ type: string;
1369
+ description?: string;
1370
+ config?: Record<string, unknown>;
1371
+ events?: Record<string, boolean>;
1372
+ }): Promise<ApiResponse<{
1373
+ success: boolean;
1374
+ connector_id: string;
1375
+ }>>;
1376
+ updateConnector(connectorId: string, updates: {
1377
+ name?: string;
1378
+ description?: string;
1379
+ config?: Record<string, unknown>;
1380
+ events?: Record<string, boolean>;
1381
+ status?: string;
1382
+ }): Promise<ApiResponse<{
1383
+ success: boolean;
1384
+ connector_id: string;
1385
+ }>>;
1386
+ deleteConnector(connectorId: string): Promise<ApiResponse<{
1387
+ success: boolean;
1388
+ }>>;
1389
+ testConnector(connectorId: string): Promise<ApiResponse<{
1390
+ success: boolean;
1391
+ event_id: string;
1392
+ status?: number;
1393
+ error?: string;
1394
+ }>>;
1395
+ getConnectorEvents(params: {
1396
+ connector_id?: string;
1397
+ project_id?: string;
1398
+ status?: string;
1399
+ limit?: number;
1400
+ offset?: number;
1401
+ }): Promise<ApiResponse<{
1402
+ events: Array<{
1403
+ id: string;
1404
+ connector_id: string;
1405
+ event_type: string;
1406
+ status: string;
1407
+ response_status?: number;
1408
+ error_message?: string;
1409
+ attempts: number;
1410
+ created_at: string;
1411
+ sent_at?: string;
1412
+ }>;
1413
+ total_count: number;
1414
+ has_more: boolean;
1415
+ }>>;
1229
1416
  }
1230
1417
  export declare function getApiClient(): VibescopeApiClient;
1231
1418
  export declare function initApiClient(config: ApiClientConfig): VibescopeApiClient;
@@ -616,6 +616,12 @@ export class VibescopeApiClient {
616
616
  limit
617
617
  });
618
618
  }
619
+ async getBodyOfWorkCosts(params) {
620
+ return this.proxy('get_body_of_work_costs', params);
621
+ }
622
+ async getSprintCosts(params) {
623
+ return this.proxy('get_sprint_costs', params);
624
+ }
619
625
  async getTokenUsage() {
620
626
  return this.proxy('get_token_usage', {});
621
627
  }
@@ -725,6 +731,48 @@ export class VibescopeApiClient {
725
731
  async abandonCheckout(params) {
726
732
  return this.proxy('abandon_checkout', params);
727
733
  }
734
+ // ============================================================================
735
+ // Worktree Management
736
+ // ============================================================================
737
+ async getStaleWorktrees(projectId) {
738
+ return this.request('GET', `/api/mcp/worktrees/stale?project_id=${projectId}`);
739
+ }
740
+ async clearWorktreePath(taskId) {
741
+ return this.request('PATCH', `/api/mcp/tasks/${taskId}`, { worktree_path: null });
742
+ }
743
+ // ============================================================================
744
+ // Connector endpoints
745
+ // ============================================================================
746
+ async getConnectors(projectId, params) {
747
+ return this.proxy('get_connectors', {
748
+ project_id: projectId,
749
+ ...params
750
+ });
751
+ }
752
+ async getConnector(connectorId) {
753
+ return this.proxy('get_connector', { connector_id: connectorId });
754
+ }
755
+ async addConnector(projectId, params) {
756
+ return this.proxy('add_connector', {
757
+ project_id: projectId,
758
+ ...params
759
+ });
760
+ }
761
+ async updateConnector(connectorId, updates) {
762
+ return this.proxy('update_connector', {
763
+ connector_id: connectorId,
764
+ ...updates
765
+ });
766
+ }
767
+ async deleteConnector(connectorId) {
768
+ return this.proxy('delete_connector', { connector_id: connectorId });
769
+ }
770
+ async testConnector(connectorId) {
771
+ return this.proxy('test_connector', { connector_id: connectorId });
772
+ }
773
+ async getConnectorEvents(params) {
774
+ return this.proxy('get_connector_events', params);
775
+ }
728
776
  }
729
777
  // Singleton instance
730
778
  let apiClient = null;
@@ -7,6 +7,7 @@
7
7
  * - get_blockers
8
8
  * - delete_blocker
9
9
  */
10
+ import { success, error } from './types.js';
10
11
  import { parseArgs, uuidValidator, createEnumValidator, VALID_BLOCKER_STATUSES, } from '../validators.js';
11
12
  import { getApiClient } from '../api-client.js';
12
13
  // Argument schemas for type-safe parsing
@@ -33,18 +34,18 @@ export const addBlocker = async (args, ctx) => {
33
34
  const apiClient = getApiClient();
34
35
  const response = await apiClient.addBlocker(project_id, description, ctx.session.currentSessionId || undefined);
35
36
  if (!response.ok) {
36
- throw new Error(response.error || 'Failed to add blocker');
37
+ return error(response.error || 'Failed to add blocker');
37
38
  }
38
- return { result: response.data };
39
+ return success(response.data);
39
40
  };
40
41
  export const resolveBlocker = async (args, _ctx) => {
41
42
  const { blocker_id, resolution_note } = parseArgs(args, resolveBlockerSchema);
42
43
  const apiClient = getApiClient();
43
44
  const response = await apiClient.resolveBlocker(blocker_id, resolution_note);
44
45
  if (!response.ok) {
45
- throw new Error(response.error || 'Failed to resolve blocker');
46
+ return error(response.error || 'Failed to resolve blocker');
46
47
  }
47
- return { result: response.data };
48
+ return success(response.data);
48
49
  };
49
50
  export const getBlockers = async (args, _ctx) => {
50
51
  const { project_id, status, limit, offset, search_query } = parseArgs(args, getBlockersSchema);
@@ -56,18 +57,18 @@ export const getBlockers = async (args, _ctx) => {
56
57
  search_query
57
58
  });
58
59
  if (!response.ok) {
59
- throw new Error(response.error || 'Failed to fetch blockers');
60
+ return error(response.error || 'Failed to fetch blockers');
60
61
  }
61
- return { result: response.data };
62
+ return success(response.data);
62
63
  };
63
64
  export const deleteBlocker = async (args, _ctx) => {
64
65
  const { blocker_id } = parseArgs(args, deleteBlockerSchema);
65
66
  const apiClient = getApiClient();
66
67
  const response = await apiClient.deleteBlocker(blocker_id);
67
68
  if (!response.ok) {
68
- throw new Error(response.error || 'Failed to delete blocker');
69
+ return error(response.error || 'Failed to delete blocker');
69
70
  }
70
- return { result: response.data };
71
+ return success(response.data);
71
72
  };
72
73
  /**
73
74
  * Blockers handlers registry
@@ -105,7 +105,7 @@ export const createBodyOfWork = async (args, ctx) => {
105
105
  instance_id: session.instanceId
106
106
  });
107
107
  if (!response.ok) {
108
- throw new Error(`Failed to create body of work: ${response.error}`);
108
+ return { result: { error: response.error || 'Failed to create body of work' }, isError: true };
109
109
  }
110
110
  return {
111
111
  result: {
@@ -135,7 +135,7 @@ export const updateBodyOfWork = async (args, ctx) => {
135
135
  deploy_trigger
136
136
  });
137
137
  if (!response.ok) {
138
- throw new Error(`Failed to update body of work: ${response.error}`);
138
+ return { result: { error: response.error || 'Failed to update body of work' }, isError: true };
139
139
  }
140
140
  return { result: { success: true, body_of_work_id } };
141
141
  };
@@ -145,7 +145,7 @@ export const getBodyOfWork = async (args, ctx) => {
145
145
  // Response type varies based on summary_only
146
146
  const response = await apiClient.proxy('get_body_of_work', { body_of_work_id, summary_only });
147
147
  if (!response.ok) {
148
- throw new Error(`Failed to get body of work: ${response.error}`);
148
+ return { result: { error: response.error || 'Failed to get body of work' }, isError: true };
149
149
  }
150
150
  return { result: response.data };
151
151
  };
@@ -160,7 +160,7 @@ export const getBodiesOfWork = async (args, ctx) => {
160
160
  search_query
161
161
  });
162
162
  if (!response.ok) {
163
- throw new Error(`Failed to fetch bodies of work: ${response.error}`);
163
+ return { result: { error: response.error || 'Failed to fetch bodies of work' }, isError: true };
164
164
  }
165
165
  return { result: response.data };
166
166
  };
@@ -171,7 +171,7 @@ export const deleteBodyOfWork = async (args, ctx) => {
171
171
  body_of_work_id
172
172
  });
173
173
  if (!response.ok) {
174
- throw new Error(`Failed to delete body of work: ${response.error}`);
174
+ return { result: { error: response.error || 'Failed to delete body of work' }, isError: true };
175
175
  }
176
176
  return { result: { success: true, message: 'Body of work deleted. Tasks are preserved.' } };
177
177
  };
@@ -185,7 +185,7 @@ export const addTaskToBodyOfWork = async (args, ctx) => {
185
185
  order_index
186
186
  });
187
187
  if (!response.ok) {
188
- throw new Error(`Failed to add task to body of work: ${response.error}`);
188
+ return { result: { error: response.error || 'Failed to add task to body of work' }, isError: true };
189
189
  }
190
190
  return { result: response.data };
191
191
  };
@@ -194,7 +194,7 @@ export const removeTaskFromBodyOfWork = async (args, ctx) => {
194
194
  const apiClient = getApiClient();
195
195
  const response = await apiClient.proxy('remove_task_from_body_of_work', { task_id });
196
196
  if (!response.ok) {
197
- throw new Error(`Failed to remove task from body of work: ${response.error}`);
197
+ return { result: { error: response.error || 'Failed to remove task from body of work' }, isError: true };
198
198
  }
199
199
  return { result: response.data };
200
200
  };
@@ -203,14 +203,14 @@ export const activateBodyOfWork = async (args, ctx) => {
203
203
  const apiClient = getApiClient();
204
204
  const response = await apiClient.proxy('activate_body_of_work', { body_of_work_id });
205
205
  if (!response.ok) {
206
- throw new Error(`Failed to activate body of work: ${response.error}`);
206
+ return { result: { error: response.error || 'Failed to activate body of work' }, isError: true };
207
207
  }
208
208
  return { result: response.data };
209
209
  };
210
210
  export const addTaskDependency = async (args, ctx) => {
211
211
  const { body_of_work_id, task_id, depends_on_task_id } = parseArgs(args, addTaskDependencySchema);
212
212
  if (task_id === depends_on_task_id) {
213
- throw new Error('A task cannot depend on itself');
213
+ return { result: { error: 'A task cannot depend on itself' }, isError: true };
214
214
  }
215
215
  const apiClient = getApiClient();
216
216
  const response = await apiClient.proxy('add_task_dependency', {
@@ -219,7 +219,7 @@ export const addTaskDependency = async (args, ctx) => {
219
219
  depends_on_task_id
220
220
  });
221
221
  if (!response.ok) {
222
- throw new Error(`Failed to add task dependency: ${response.error}`);
222
+ return { result: { error: response.error || 'Failed to add task dependency' }, isError: true };
223
223
  }
224
224
  return { result: response.data };
225
225
  };
@@ -231,14 +231,14 @@ export const removeTaskDependency = async (args, ctx) => {
231
231
  depends_on_task_id
232
232
  });
233
233
  if (!response.ok) {
234
- throw new Error(`Failed to remove task dependency: ${response.error}`);
234
+ return { result: { error: response.error || 'Failed to remove task dependency' }, isError: true };
235
235
  }
236
236
  return { result: response.data };
237
237
  };
238
238
  export const getTaskDependencies = async (args, ctx) => {
239
239
  const { body_of_work_id, task_id } = parseArgs(args, getTaskDependenciesSchema);
240
240
  if (!body_of_work_id && !task_id) {
241
- throw new Error('Either body_of_work_id or task_id is required');
241
+ return { result: { error: 'Either body_of_work_id or task_id is required' }, isError: true };
242
242
  }
243
243
  const apiClient = getApiClient();
244
244
  const response = await apiClient.proxy('get_task_dependencies', {
@@ -246,7 +246,7 @@ export const getTaskDependencies = async (args, ctx) => {
246
246
  task_id
247
247
  });
248
248
  if (!response.ok) {
249
- throw new Error(`Failed to fetch task dependencies: ${response.error}`);
249
+ return { result: { error: response.error || 'Failed to fetch task dependencies' }, isError: true };
250
250
  }
251
251
  return { result: response.data };
252
252
  };
@@ -255,7 +255,7 @@ export const getNextBodyOfWorkTask = async (args, ctx) => {
255
255
  const apiClient = getApiClient();
256
256
  const response = await apiClient.proxy('get_next_body_of_work_task', { body_of_work_id });
257
257
  if (!response.ok) {
258
- throw new Error(`Failed to get next body of work task: ${response.error}`);
258
+ return { result: { error: response.error || 'Failed to get next body of work task' }, isError: true };
259
259
  }
260
260
  return { result: response.data };
261
261
  };
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Connectors Handlers
3
+ *
4
+ * Handles external integration management:
5
+ * - get_connectors
6
+ * - get_connector
7
+ * - add_connector
8
+ * - update_connector
9
+ * - delete_connector
10
+ * - test_connector
11
+ * - get_connector_events
12
+ */
13
+ import type { Handler, HandlerRegistry } from './types.js';
14
+ /**
15
+ * Get all connectors for a project
16
+ */
17
+ export declare const getConnectors: Handler;
18
+ /**
19
+ * Get a single connector with full details
20
+ */
21
+ export declare const getConnector: Handler;
22
+ /**
23
+ * Add a new connector
24
+ */
25
+ export declare const addConnector: Handler;
26
+ /**
27
+ * Update a connector
28
+ */
29
+ export declare const updateConnector: Handler;
30
+ /**
31
+ * Delete a connector
32
+ */
33
+ export declare const deleteConnector: Handler;
34
+ /**
35
+ * Test a connector by sending a test event
36
+ */
37
+ export declare const testConnector: Handler;
38
+ /**
39
+ * Get connector event history
40
+ */
41
+ export declare const getConnectorEvents: Handler;
42
+ /**
43
+ * Connectors handlers registry
44
+ */
45
+ export declare const connectorHandlers: HandlerRegistry;