mcp-quickbase 2.0.5 → 2.2.0

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 (146) hide show
  1. package/.crewchief/runs/state.json +3 -0
  2. package/.mcp.json +6 -32
  3. package/.sdd/tickets/RELS_relationship-management/README.md +98 -0
  4. package/.sdd/tickets/RELS_relationship-management/planning/analysis.md +190 -0
  5. package/.sdd/tickets/RELS_relationship-management/planning/architecture.md +413 -0
  6. package/.sdd/tickets/RELS_relationship-management/planning/plan.md +177 -0
  7. package/.sdd/tickets/RELS_relationship-management/planning/quality-strategy.md +335 -0
  8. package/.sdd/tickets/RELS_relationship-management/planning/review-updates.md +95 -0
  9. package/.sdd/tickets/RELS_relationship-management/planning/security-review.md +213 -0
  10. package/.sdd/tickets/RELS_relationship-management/planning/ticket-review.md +885 -0
  11. package/.sdd/tickets/RELS_relationship-management/tasks/RELS.1001_domain-setup.md +96 -0
  12. package/.sdd/tickets/RELS_relationship-management/tasks/RELS.1002_get-relationships-tool.md +142 -0
  13. package/.sdd/tickets/RELS_relationship-management/tasks/RELS.1003_register-phase1-tools.md +105 -0
  14. package/.sdd/tickets/RELS_relationship-management/tasks/RELS.2001_create-relationship-tool.md +151 -0
  15. package/.sdd/tickets/RELS_relationship-management/tasks/RELS.2002_update-relationship-tool.md +145 -0
  16. package/.sdd/tickets/RELS_relationship-management/tasks/RELS.3001_delete-relationship-tool.md +154 -0
  17. package/.sdd/tickets/RELS_relationship-management/tasks/RELS.4001_integration-testing.md +159 -0
  18. package/.sdd/tickets/RELS_relationship-management/tasks/RELS.4002_final-verification.md +182 -0
  19. package/.sdd/tickets/RELS_relationship-management/tasks/RELS_TASK_INDEX.md +179 -0
  20. package/crewchief.config.js +31 -0
  21. package/dist/client/quickbase.d.ts +7 -2
  22. package/dist/client/quickbase.js +64 -51
  23. package/dist/client/quickbase.js.map +1 -1
  24. package/dist/mcp/index.d.ts +1 -1
  25. package/dist/mcp/server.d.ts +3 -3
  26. package/dist/mcp/server.js +21 -17
  27. package/dist/mcp/server.js.map +1 -1
  28. package/dist/mcp-stdio-server.js +64 -49
  29. package/dist/mcp-stdio-server.js.map +1 -1
  30. package/dist/server.js +84 -83
  31. package/dist/server.js.map +1 -1
  32. package/dist/tools/apps/create_app.d.ts +2 -2
  33. package/dist/tools/apps/create_app.js +23 -23
  34. package/dist/tools/apps/create_app.js.map +1 -1
  35. package/dist/tools/apps/index.d.ts +4 -4
  36. package/dist/tools/apps/index.js +3 -3
  37. package/dist/tools/apps/list_tables.d.ts +7 -7
  38. package/dist/tools/apps/list_tables.js +28 -27
  39. package/dist/tools/apps/list_tables.js.map +1 -1
  40. package/dist/tools/apps/update_app.d.ts +2 -2
  41. package/dist/tools/apps/update_app.js +28 -26
  42. package/dist/tools/apps/update_app.js.map +1 -1
  43. package/dist/tools/base.d.ts +3 -3
  44. package/dist/tools/base.js +7 -7
  45. package/dist/tools/base.js.map +1 -1
  46. package/dist/tools/configure_cache.d.ts +3 -3
  47. package/dist/tools/configure_cache.js +16 -16
  48. package/dist/tools/configure_cache.js.map +1 -1
  49. package/dist/tools/fields/create_field.d.ts +8 -7
  50. package/dist/tools/fields/create_field.js +39 -29
  51. package/dist/tools/fields/create_field.js.map +1 -1
  52. package/dist/tools/fields/delete_field.d.ts +79 -0
  53. package/dist/tools/fields/delete_field.js +105 -0
  54. package/dist/tools/fields/delete_field.js.map +1 -0
  55. package/dist/tools/fields/get_field.d.ts +91 -0
  56. package/dist/tools/fields/get_field.js +82 -0
  57. package/dist/tools/fields/get_field.js.map +1 -0
  58. package/dist/tools/fields/index.d.ts +5 -3
  59. package/dist/tools/fields/index.js +11 -5
  60. package/dist/tools/fields/index.js.map +1 -1
  61. package/dist/tools/fields/update_field.d.ts +7 -15
  62. package/dist/tools/fields/update_field.js +39 -38
  63. package/dist/tools/fields/update_field.js.map +1 -1
  64. package/dist/tools/files/download_file.d.ts +2 -2
  65. package/dist/tools/files/download_file.js +35 -35
  66. package/dist/tools/files/download_file.js.map +1 -1
  67. package/dist/tools/files/index.d.ts +3 -3
  68. package/dist/tools/files/index.js +3 -3
  69. package/dist/tools/files/upload_file.d.ts +2 -2
  70. package/dist/tools/files/upload_file.js +52 -44
  71. package/dist/tools/files/upload_file.js.map +1 -1
  72. package/dist/tools/index.d.ts +13 -12
  73. package/dist/tools/index.js +6 -3
  74. package/dist/tools/index.js.map +1 -1
  75. package/dist/tools/records/bulk_create_records.d.ts +2 -2
  76. package/dist/tools/records/bulk_create_records.js +28 -28
  77. package/dist/tools/records/bulk_create_records.js.map +1 -1
  78. package/dist/tools/records/bulk_update_records.d.ts +2 -2
  79. package/dist/tools/records/bulk_update_records.js +27 -27
  80. package/dist/tools/records/bulk_update_records.js.map +1 -1
  81. package/dist/tools/records/create_record.d.ts +2 -2
  82. package/dist/tools/records/create_record.js +40 -40
  83. package/dist/tools/records/create_record.js.map +1 -1
  84. package/dist/tools/records/index.d.ts +6 -6
  85. package/dist/tools/records/index.js +3 -3
  86. package/dist/tools/records/query_records.d.ts +3 -3
  87. package/dist/tools/records/query_records.js +82 -78
  88. package/dist/tools/records/query_records.js.map +1 -1
  89. package/dist/tools/records/update_record.d.ts +2 -2
  90. package/dist/tools/records/update_record.js +31 -29
  91. package/dist/tools/records/update_record.js.map +1 -1
  92. package/dist/tools/registry.d.ts +1 -1
  93. package/dist/tools/registry.js +1 -1
  94. package/dist/tools/relationships/create_relationship.d.ts +150 -0
  95. package/dist/tools/relationships/create_relationship.js +181 -0
  96. package/dist/tools/relationships/create_relationship.js.map +1 -0
  97. package/dist/tools/relationships/delete_relationship.d.ts +66 -0
  98. package/dist/tools/relationships/delete_relationship.js +85 -0
  99. package/dist/tools/relationships/delete_relationship.js.map +1 -0
  100. package/dist/tools/relationships/get_relationships.d.ts +126 -0
  101. package/dist/tools/relationships/get_relationships.js +126 -0
  102. package/dist/tools/relationships/get_relationships.js.map +1 -0
  103. package/dist/tools/relationships/index.d.ts +14 -0
  104. package/dist/tools/relationships/index.js +37 -0
  105. package/dist/tools/relationships/index.js.map +1 -0
  106. package/dist/tools/relationships/update_relationship.d.ts +139 -0
  107. package/dist/tools/relationships/update_relationship.js +168 -0
  108. package/dist/tools/relationships/update_relationship.js.map +1 -0
  109. package/dist/tools/reports/index.d.ts +2 -2
  110. package/dist/tools/reports/index.js +3 -3
  111. package/dist/tools/reports/run_report.d.ts +3 -3
  112. package/dist/tools/reports/run_report.js +29 -29
  113. package/dist/tools/reports/run_report.js.map +1 -1
  114. package/dist/tools/tables/create_table.d.ts +2 -49
  115. package/dist/tools/tables/create_table.js +26 -49
  116. package/dist/tools/tables/create_table.js.map +1 -1
  117. package/dist/tools/tables/get_table_fields.d.ts +2 -2
  118. package/dist/tools/tables/get_table_fields.js +25 -25
  119. package/dist/tools/tables/get_table_fields.js.map +1 -1
  120. package/dist/tools/tables/index.d.ts +4 -4
  121. package/dist/tools/tables/index.js +3 -3
  122. package/dist/tools/tables/update_table.d.ts +2 -2
  123. package/dist/tools/tables/update_table.js +28 -26
  124. package/dist/tools/tables/update_table.js.map +1 -1
  125. package/dist/tools/test_connection.d.ts +2 -2
  126. package/dist/tools/test_connection.js +28 -28
  127. package/dist/tools/test_connection.js.map +1 -1
  128. package/dist/types/api.d.ts +1 -1
  129. package/dist/types/mcp.d.ts +1 -1
  130. package/dist/utils/cache.js +16 -16
  131. package/dist/utils/cache.js.map +1 -1
  132. package/dist/utils/file.js +44 -40
  133. package/dist/utils/file.js.map +1 -1
  134. package/dist/utils/logger.js +30 -28
  135. package/dist/utils/logger.js.map +1 -1
  136. package/dist/utils/retry.js +10 -10
  137. package/dist/utils/retry.js.map +1 -1
  138. package/dist/utils/validation.d.ts +1 -1
  139. package/dist/utils/validation.js +39 -36
  140. package/dist/utils/validation.js.map +1 -1
  141. package/docs/README.md +6 -0
  142. package/docs/future-improvements.md +33 -0
  143. package/docs/migration-guide.md +160 -0
  144. package/docs/release-notes.md +89 -0
  145. package/package.json +5 -4
  146. /package/{HARDENING_SUMMARY.md → docs/hardening-summary.md} +0 -0
@@ -0,0 +1,413 @@
1
+ # Architecture: Relationship Management
2
+
3
+ ## Overview
4
+
5
+ This feature adds a new `relationships` domain to the MCP Quickbase server, following the established patterns used by other domains (apps, tables, fields, etc.). The implementation consists of four tools mapping directly to the Quickbase Relationships API endpoints, with special attention to tool descriptions that clearly communicate destructive behavior to AI agents.
6
+
7
+ ## Design Decisions
8
+
9
+ ### Decision 1: Separate Relationships Domain
10
+
11
+ **Context:** Relationships could be implemented as part of the `tables` domain or as a new domain.
12
+
13
+ **Decision:** Create a new `src/tools/relationships/` domain directory.
14
+
15
+ **Rationale:**
16
+ - Follows existing pattern where each API resource area has its own domain
17
+ - Provides clear separation of concerns
18
+ - Allows for future expansion (e.g., cross-app relationship tools)
19
+ - Consistent with how `fields`, `records`, `files`, `reports` are organized
20
+
21
+ ### Decision 2: Agent-Safety-First Tool Descriptions
22
+
23
+ **Context:** The delete operation is highly destructive, and agents may use tools without fully understanding consequences.
24
+
25
+ **Decision:** Implement a description format that:
26
+ 1. Starts with clear action statement
27
+ 2. Includes WARNING label for destructive operations
28
+ 3. Lists exactly what will be deleted/lost
29
+ 4. Suggests safer alternatives where applicable
30
+ 5. Recommends user confirmation for destructive operations
31
+
32
+ **Rationale:**
33
+ - MCP tool descriptions are the primary way agents understand tool behavior
34
+ - Explicit warnings reduce risk of unintended data loss
35
+ - Following patterns from other enterprise API tools
36
+ - Aligns with user requirement for "clearly indicate potentially destructive changes"
37
+
38
+ ### Decision 3: Flat Parameter Structure
39
+
40
+ **Context:** The API has nested structures for summary fields (accumulationType, where, label).
41
+
42
+ **Decision:** Use flat parameter structures with clear naming:
43
+ ```typescript
44
+ {
45
+ summary_field_id: number;
46
+ summary_label: string;
47
+ summary_accumulation_type: string;
48
+ summary_where?: string;
49
+ }
50
+ ```
51
+
52
+ **Rationale:**
53
+ - Matches existing tool patterns (e.g., `create_field`)
54
+ - Simpler for agents to construct
55
+ - Reduces nesting complexity in JSON Schema
56
+ - Clear parameter names are self-documenting
57
+
58
+ ### Decision 4: TypeScript Interfaces for API Types
59
+
60
+ **Context:** Need to represent Quickbase API response types.
61
+
62
+ **Decision:** Define interfaces in each tool file for params and results, following existing patterns.
63
+
64
+ **Rationale:**
65
+ - Consistent with existing codebase (see `create_table.ts`, `create_field.ts`)
66
+ - Keeps related types close to their usage
67
+ - Enables strong typing throughout
68
+
69
+ ## Technology Choices
70
+
71
+ | Component | Choice | Rationale |
72
+ |-----------|--------|-----------|
73
+ | Language | TypeScript | Existing codebase uses TypeScript with strict mode |
74
+ | Validation | Zod (via base class) | Already integrated in BaseTool |
75
+ | HTTP Client | QuickbaseClient | Existing client with retry, caching, rate limiting |
76
+ | Testing | Jest | Existing test framework |
77
+ | Linting | ESLint + Prettier | Existing configuration |
78
+
79
+ ## Component Design
80
+
81
+ ### Directory Structure
82
+
83
+ ```
84
+ src/tools/relationships/
85
+ index.ts # Domain registration and exports
86
+ get_relationships.ts # GET /relationships tool
87
+ create_relationship.ts # POST /relationships tool
88
+ update_relationship.ts # POST /relationships/{id} tool
89
+ delete_relationship.ts # DELETE /relationships/{id} tool
90
+ ```
91
+
92
+ ### Component 1: GetRelationshipsTool
93
+
94
+ **Responsibilities:**
95
+ - Query all relationships for a given table
96
+ - Support pagination (skip parameter)
97
+ - Return relationship metadata including lookup and summary fields
98
+
99
+ **Interface:**
100
+ ```typescript
101
+ interface GetRelationshipsParams {
102
+ table_id: string; // Required: Child table ID (DBID)
103
+ skip?: number; // Optional: Pagination offset
104
+ }
105
+
106
+ interface GetRelationshipsResult {
107
+ relationships: Relationship[];
108
+ metadata: {
109
+ totalRelationships: number;
110
+ numRelationships: number;
111
+ skip: number;
112
+ };
113
+ }
114
+ ```
115
+
116
+ **Description Format:**
117
+ ```
118
+ Gets all table-to-table relationships for a specified table. Returns both relationships
119
+ where this table is the child (has reference fields pointing to parents) and where this
120
+ table is the parent (has child tables referencing it). Use this tool to explore table
121
+ structure and understand data connections before modifying relationships.
122
+ ```
123
+
124
+ ### Component 2: CreateRelationshipTool
125
+
126
+ **Responsibilities:**
127
+ - Create new relationship between tables
128
+ - Optionally create lookup fields during creation
129
+ - Optionally create summary field during creation
130
+
131
+ **Interface:**
132
+ ```typescript
133
+ interface CreateRelationshipParams {
134
+ table_id: string; // Required: Child table ID
135
+ parent_table_id: string; // Required: Parent table ID
136
+ foreign_key_label?: string; // Optional: Label for reference field
137
+ lookup_field_ids?: number[]; // Optional: Parent field IDs to create as lookups
138
+ summary_field_id?: number; // Optional: Child field ID to summarize
139
+ summary_label?: string; // Optional: Label for summary field
140
+ summary_accumulation_type?: string; // Required if summary_field_id: SUM/COUNT/AVG/MAX/MIN
141
+ summary_where?: string; // Optional: Quickbase query filter for summary
142
+ }
143
+
144
+ // Note: JSON Schema validation must enforce that summary_accumulation_type is required
145
+ // when summary_field_id is provided. Use conditional validation in paramSchema.
146
+
147
+ interface CreateRelationshipResult {
148
+ id: number;
149
+ parentTableId: string;
150
+ childTableId: string;
151
+ foreignKeyField: FieldInfo;
152
+ lookupFields: FieldInfo[];
153
+ summaryFields: FieldInfo[];
154
+ }
155
+ ```
156
+
157
+ **Description Format:**
158
+ ```
159
+ Creates a new table-to-table relationship linking a child table to a parent table.
160
+ This creates a reference field in the child table. Optionally creates lookup fields
161
+ (to display parent data in child records) and/or a summary field (to aggregate child
162
+ data in parent records). Relationships can only be created between tables in the same
163
+ application. This operation is SAFE and does not modify existing data.
164
+ ```
165
+
166
+ ### Component 3: UpdateRelationshipTool
167
+
168
+ **Responsibilities:**
169
+ - Add lookup fields to existing relationship
170
+ - Add summary field to existing relationship
171
+ - Does NOT delete existing fields (additive only)
172
+
173
+ **Interface:**
174
+ ```typescript
175
+ interface UpdateRelationshipParams {
176
+ table_id: string; // Required: Child table ID
177
+ relationship_id: number; // Required: Relationship ID (foreign key field ID)
178
+ lookup_field_ids?: number[]; // Optional: Additional parent field IDs for lookups
179
+ summary_field_id?: number; // Optional: Child field ID to summarize
180
+ summary_label?: string; // Optional: Label for summary field
181
+ summary_accumulation_type?: string; // Required if summary_field_id
182
+ summary_where?: string; // Optional: Quickbase query filter
183
+ }
184
+
185
+ // Note: JSON Schema validation must enforce that summary_accumulation_type is required
186
+ // when summary_field_id is provided. Use conditional validation in paramSchema.
187
+
188
+ interface UpdateRelationshipResult {
189
+ id: number;
190
+ parentTableId: string;
191
+ childTableId: string;
192
+ foreignKeyField: FieldInfo;
193
+ lookupFields: FieldInfo[];
194
+ summaryFields: FieldInfo[];
195
+ }
196
+ ```
197
+
198
+ **Description Format:**
199
+ ```
200
+ Adds lookup fields and/or summary fields to an existing relationship. This operation
201
+ is ADDITIVE ONLY - it will not delete existing lookup or summary fields. Use this to
202
+ enhance relationships with additional calculated fields. To remove fields from a
203
+ relationship, you must delete them individually using the field deletion tools.
204
+ ```
205
+
206
+ ### Component 4: DeleteRelationshipTool
207
+
208
+ **Responsibilities:**
209
+ - Delete entire relationship
210
+ - Clearly warn about data loss in description
211
+ - Return confirmation of what was deleted
212
+
213
+ **Interface:**
214
+ ```typescript
215
+ interface DeleteRelationshipParams {
216
+ table_id: string; // Required: Child table ID
217
+ relationship_id: number; // Required: Relationship ID to delete
218
+ }
219
+
220
+ interface DeleteRelationshipResult {
221
+ relationshipId: number;
222
+ deleted: boolean;
223
+ }
224
+ ```
225
+
226
+ **Description Format (Critical for Agent Safety):**
227
+ ```
228
+ WARNING: DESTRUCTIVE OPERATION - Permanently deletes an entire table-to-table
229
+ relationship INCLUDING ALL LOOKUP AND SUMMARY FIELDS associated with it. All data
230
+ in those fields will be permanently lost and CANNOT be recovered. The reference
231
+ field in the child table will NOT be deleted (it will remain and may need to be
232
+ manually deleted using field deletion tools if no longer needed). Before using
233
+ this tool:
234
+ 1. Use get_relationships to see what fields will be deleted
235
+ 2. Confirm with the user that they want to proceed
236
+ 3. Consider if you only need to delete specific fields instead
237
+
238
+ Only use this tool when you are certain the entire relationship should be removed.
239
+ ```
240
+
241
+ ### Shared Types
242
+
243
+ ```typescript
244
+ interface FieldInfo {
245
+ id: number;
246
+ label: string;
247
+ type: string;
248
+ }
249
+
250
+ interface Relationship {
251
+ id: number;
252
+ parentTableId: string;
253
+ childTableId: string;
254
+ foreignKeyField: FieldInfo;
255
+ isCrossApp: boolean;
256
+ lookupFields: FieldInfo[];
257
+ summaryFields: FieldInfo[];
258
+ }
259
+ ```
260
+
261
+ ## Data Flow
262
+
263
+ ### Get Relationships Flow
264
+
265
+ ```
266
+ Agent Request
267
+ |
268
+ v
269
+ GetRelationshipsTool.execute(params)
270
+ |
271
+ v
272
+ BaseTool.validateParams(params)
273
+ |
274
+ v
275
+ QuickbaseClient.request({
276
+ method: 'GET',
277
+ path: `/tables/${tableId}/relationships`,
278
+ params: { skip }
279
+ })
280
+ |
281
+ v
282
+ Transform API Response
283
+ |
284
+ v
285
+ Return GetRelationshipsResult
286
+ ```
287
+
288
+ ### Create Relationship Flow
289
+
290
+ ```
291
+ Agent Request
292
+ |
293
+ v
294
+ CreateRelationshipTool.execute(params)
295
+ |
296
+ v
297
+ BaseTool.validateParams(params)
298
+ |
299
+ v
300
+ Build Request Body (parentTableId, lookupFieldIds, summaryFields)
301
+ |
302
+ v
303
+ QuickbaseClient.request({
304
+ method: 'POST',
305
+ path: `/tables/${tableId}/relationships`,
306
+ body: requestBody
307
+ })
308
+ |
309
+ v
310
+ Transform API Response
311
+ |
312
+ v
313
+ Return CreateRelationshipResult
314
+ ```
315
+
316
+ ### Delete Relationship Flow
317
+
318
+ ```
319
+ Agent Request
320
+ |
321
+ v
322
+ DeleteRelationshipTool.execute(params)
323
+ |
324
+ v
325
+ BaseTool.validateParams(params)
326
+ |
327
+ v
328
+ QuickbaseClient.request({
329
+ method: 'DELETE',
330
+ path: `/tables/${tableId}/relationships/${relationshipId}`
331
+ })
332
+ |
333
+ v
334
+ Return DeleteRelationshipResult (confirmation)
335
+ ```
336
+
337
+ ## Integration Points
338
+
339
+ ### Tool Registration
340
+
341
+ Update `src/tools/index.ts`:
342
+ ```typescript
343
+ import { registerRelationshipTools } from './relationships';
344
+
345
+ export function initializeTools(client: QuickbaseClient, cacheService: CacheService): void {
346
+ // ... existing registrations ...
347
+
348
+ // Register relationship management tools
349
+ registerRelationshipTools(client);
350
+
351
+ // ...
352
+ }
353
+
354
+ export * from './relationships';
355
+ ```
356
+
357
+ ### API Endpoints
358
+
359
+ All tools use the existing `QuickbaseClient.request()` method with these endpoints:
360
+
361
+ | Tool | Method | Path |
362
+ |------|--------|------|
363
+ | get_relationships | GET | `/tables/{tableId}/relationships` |
364
+ | create_relationship | POST | `/tables/{tableId}/relationships` |
365
+ | update_relationship | POST | `/tables/{tableId}/relationships/{relationshipId}` |
366
+ | delete_relationship | DELETE | `/tables/{tableId}/relationships/{relationshipId}` |
367
+
368
+ ### Caching Behavior
369
+
370
+ - GET requests are cached by `QuickbaseClient` by default
371
+ - Create/Update/Delete requests skip cache and may invalidate related cached data
372
+ - Consider adding `skipCache: true` for relationship queries if stale data is problematic
373
+
374
+ ## Performance Considerations
375
+
376
+ ### Rate Limiting
377
+
378
+ - Existing rate limiter (10 req/sec default) handles all requests
379
+ - Relationship operations are typically low-volume
380
+ - No special performance optimizations needed
381
+
382
+ ### Response Size
383
+
384
+ - `get_relationships` may return large responses for tables with many relationships
385
+ - Pagination (skip parameter) is available for large result sets
386
+ - No need for custom pagination handling beyond exposing skip parameter
387
+
388
+ ## Maintainability
389
+
390
+ ### Code Organization
391
+
392
+ - Each tool in its own file with params/result interfaces
393
+ - Shared types can be extracted to a types file if needed later
394
+ - Registration pattern keeps index.ts clean
395
+
396
+ ### Error Handling
397
+
398
+ - Use existing `ApiResponse` pattern with success/error states
399
+ - Throw descriptive errors that bubble up through BaseTool
400
+ - Include table ID and relationship ID in error context
401
+
402
+ ### Documentation
403
+
404
+ - Tool descriptions serve as primary documentation for agents
405
+ - JSDoc comments on interfaces for developer documentation
406
+ - README update for human users
407
+
408
+ ### Testing Strategy
409
+
410
+ - Unit tests for each tool following existing patterns
411
+ - Mock QuickbaseClient for isolation
412
+ - Test success, validation errors, API errors, and edge cases
413
+ - Specific tests for destructive operation handling
@@ -0,0 +1,177 @@
1
+ # Plan: Relationship Management
2
+
3
+ ## Overview
4
+
5
+ This document outlines the phased execution plan for implementing relationship management tools in the MCP Quickbase server. The plan follows a safety-first approach: read-only operations first, then write operations with explicit safety measures for destructive actions.
6
+
7
+ ## Phases
8
+
9
+ ### Phase 1: Foundation - Read Operations and Domain Setup
10
+
11
+ **Objective:** Establish the relationships domain and implement the read-only `get_relationships` tool, enabling agents to explore table structures safely.
12
+
13
+ **Deliverables:**
14
+ - `src/tools/relationships/` directory structure
15
+ - `src/tools/relationships/index.ts` with registration function
16
+ - `src/tools/relationships/get_relationships.ts` tool implementation
17
+ - `src/__tests__/tools/relationships.test.ts` with tests for get_relationships
18
+ - Update to `src/tools/index.ts` to register relationship tools
19
+
20
+ **Agent Assignments:**
21
+ - implement-feature: Create directory structure and index.ts registration pattern
22
+ - implement-feature: Implement GetRelationshipsTool with full type definitions
23
+ - implement-feature: Update main tools/index.ts to include relationships
24
+
25
+ **Acceptance Criteria:**
26
+ - [ ] `get_relationships` tool is registered and callable
27
+ - [ ] Returns correct relationship structure with foreignKeyField, lookupFields, summaryFields
28
+ - [ ] **API response structure validated against TypeScript interfaces** - Confirm actual Quickbase API responses match documented structure before proceeding to Phase 2
29
+ - [ ] Pagination (skip parameter) works correctly - Verify if API supports limit parameter and adjust if needed
30
+ - [ ] Tool description clearly explains what information is returned
31
+ - [ ] Unit tests cover success case, empty results, pagination, and API errors
32
+
33
+ ### Phase 2: Write Operations - Create and Update
34
+
35
+ **Objective:** Implement non-destructive write operations that allow creating and enhancing relationships.
36
+
37
+ **Deliverables:**
38
+ - `src/tools/relationships/create_relationship.ts` tool implementation
39
+ - `src/tools/relationships/update_relationship.ts` tool implementation
40
+ - Extended tests in `src/__tests__/tools/relationships.test.ts`
41
+
42
+ **Agent Assignments:**
43
+ - implement-feature: Implement CreateRelationshipTool with lookup/summary field support
44
+ - implement-feature: Implement UpdateRelationshipTool (additive operations only)
45
+
46
+ **Acceptance Criteria:**
47
+ - [ ] `create_relationship` tool creates relationships with optional lookup/summary fields
48
+ - [ ] Tool description emphasizes this is a SAFE operation
49
+ - [ ] **JSON Schema conditional validation enforced** - summary_accumulation_type is required when summary_field_id is provided
50
+ - [ ] `update_relationship` tool adds fields to existing relationships
51
+ - [ ] Update tool description clearly states "ADDITIVE ONLY"
52
+ - [ ] Unit tests cover: basic creation, creation with lookups, creation with summary, validation errors
53
+ - [ ] Unit tests cover: update adding lookups, update adding summary, relationship not found
54
+ - [ ] Unit tests verify conditional validation: missing accumulation_type with summary_field_id fails validation
55
+
56
+ ### Phase 3: Destructive Operations with Safety Measures
57
+
58
+ **Objective:** Implement the delete operation with comprehensive safety warnings and agent guidance.
59
+
60
+ **Deliverables:**
61
+ - `src/tools/relationships/delete_relationship.ts` tool implementation
62
+ - Complete test coverage for delete scenarios
63
+ - Final documentation updates
64
+
65
+ **Agent Assignments:**
66
+ - implement-feature: Implement DeleteRelationshipTool with safety-focused description
67
+ - implement-feature: Ensure all tests pass and coverage threshold met
68
+ - implement-feature: Update exports and verify tool registration
69
+
70
+ **Acceptance Criteria:**
71
+ - [ ] `delete_relationship` tool description starts with "WARNING: DESTRUCTIVE OPERATION"
72
+ - [ ] Description explicitly lists what will be deleted (lookup fields, summary fields)
73
+ - [ ] Description explicitly states data is permanently lost
74
+ - [ ] Description recommends using `get_relationships` first to review impact
75
+ - [ ] Description recommends confirming with user before proceeding
76
+ - [ ] Unit tests cover: successful deletion, relationship not found, API errors
77
+ - [ ] All four tools are registered and functional
78
+ - [ ] Test coverage meets or exceeds 40% threshold (lines/functions/statements) and 20% branches per jest.config.js
79
+
80
+ ### Phase 4: Integration and Verification
81
+
82
+ **Objective:** Verify complete integration, ensure all tests pass, and validate agent safety measures.
83
+
84
+ **Deliverables:**
85
+ - Passing test suite with coverage >= 40% (lines/functions/statements) and >= 20% branches per jest.config.js
86
+ - All linting checks pass
87
+ - Verified tool descriptions for agent safety
88
+
89
+ **Agent Assignments:**
90
+ - verify-task: Run full test suite and validate coverage
91
+ - verify-task: Verify all tools are properly registered
92
+ - verify-task: Review tool descriptions for clarity and safety warnings
93
+ - commit-task: Commit all changes with descriptive message
94
+
95
+ **Acceptance Criteria:**
96
+ - [ ] `npm test` passes all tests
97
+ - [ ] `npm run lint` shows no errors
98
+ - [ ] All four relationship tools appear in tool registry
99
+ - [ ] Delete tool description contains required safety warnings
100
+ - [ ] Integration test validates end-to-end flow (if applicable)
101
+
102
+ ## Dependencies
103
+
104
+ ### Cross-Phase Dependencies
105
+
106
+ ```
107
+ Phase 1 (Foundation)
108
+ |
109
+ +---> Phase 2 (Create/Update) [depends on domain setup]
110
+ |
111
+ +---> Phase 3 (Delete) [depends on domain setup, benefits from Phase 2 patterns]
112
+ |
113
+ +---> Phase 4 (Verification) [depends on all implementations]
114
+ ```
115
+
116
+ ### External Dependencies
117
+
118
+ | Dependency | Type | Status |
119
+ |------------|------|--------|
120
+ | `src/tools/base.ts` (BaseTool) | Existing | Available |
121
+ | `src/client/quickbase.ts` (QuickbaseClient) | Existing | Available |
122
+ | `src/tools/registry.ts` (toolRegistry) | Existing | Available |
123
+ | Quickbase Relationships API | External | Available |
124
+
125
+ ## Risk Mitigation
126
+
127
+ | Risk | Probability | Impact | Mitigation |
128
+ |------|-------------|--------|------------|
129
+ | API schema differs from documentation | Medium | Medium | Start with get_relationships to validate response structure; adjust types as needed |
130
+ | Agent uses delete without understanding consequences | Medium | High | Comprehensive warning in tool description; recommend user confirmation |
131
+ | Test coverage falls below threshold | Low | Medium | Write tests concurrently with implementation; prioritize critical paths |
132
+ | Validation complexity for summary fields | Medium | Low | Clear error messages when accumulation_type missing; follow existing field patterns |
133
+
134
+ ## Success Metrics
135
+
136
+ - [ ] All four relationship tools implemented and registered
137
+ - [ ] `get_relationships` returns accurate relationship data
138
+ - [ ] `create_relationship` successfully creates relationships with lookup/summary fields
139
+ - [ ] `update_relationship` adds fields without deleting existing ones
140
+ - [ ] `delete_relationship` has prominent destructive operation warnings
141
+ - [ ] Test coverage >= 40% lines/functions/statements, >= 20% branches (per jest.config.js)
142
+ - [ ] No lint errors
143
+ - [ ] Tool descriptions help agents understand when to use each tool
144
+ - [ ] Destructive operations clearly marked and explain consequences
145
+
146
+ ## Implementation Notes
147
+
148
+ ### Tool Naming Convention
149
+
150
+ Follow existing snake_case pattern:
151
+ - `get_relationships` (not `getRelationships`)
152
+ - `create_relationship` (not `createRelationship`)
153
+ - `update_relationship` (not `updateRelationship`)
154
+ - `delete_relationship` (not `deleteRelationship`)
155
+
156
+ ### Parameter Naming Convention
157
+
158
+ Follow existing patterns:
159
+ - `table_id` (not `tableId`)
160
+ - `relationship_id` (not `relationshipId`)
161
+ - `parent_table_id` (not `parentTableId`)
162
+ - `lookup_field_ids` (not `lookupFieldIds`)
163
+
164
+ ### Error Message Format
165
+
166
+ Include context for debugging:
167
+ ```typescript
168
+ throw new Error(`Failed to get relationships for table ${tableId}: ${response.error?.message || 'Unknown error'}`);
169
+ ```
170
+
171
+ ### Logging Pattern
172
+
173
+ Use existing logger:
174
+ ```typescript
175
+ const logger = createLogger('GetRelationshipsTool');
176
+ logger.info('Getting relationships for table', { tableId });
177
+ ```