# Implementation Plan: DB Planet MCP Tools Refactoring ## Overview Refactor the DB Planet MCP Server from a single monolithic `SearchDBPlanet` tool into ~28 focused, single-responsibility MCP tools organized across 9 registration modules. The implementation proceeds bottom-up: shared infrastructure first (error handler, enhanced client), then tool registration modules by capability area, then wiring everything together in the barrel and server entry point. ## Tasks - [x] 1. Set up test infrastructure and shared utilities - [x] 1.1 Add vitest and fast-check dev dependencies - Run `npm install --save-dev vitest fast-check` - Add `"test": "vitest --run"` script to package.json - Add vitest config if needed (ESM + TypeScript) - _Requirements: N/A (infrastructure)_ - [x] 1.2 Create the shared error handler at `src/errorHandler.ts` - Implement `handleApiError(error: unknown): CallToolResult` - Map 401 → authentication failed, 403 → insufficient permissions, 404 → not found, timeout → timed out, other → status + message - All responses: `{ isError: true, content: [{ type: 'text', text: '[{status}] {message}' }] }` - _Requirements: 12.1, 12.2, 12.3, 12.4, 12.5_ - [ ]* 1.3 Write property test for error handler (Property 3) - **Property 3: Error handler maps HTTP status to correct MCP error** - Generate arbitrary HTTP status codes and verify the output shape and message mapping - **Validates: Requirements 12.1, 12.2, 12.3, 12.4, 12.5** - [x] 2. Enhance HaiiloClient with generic request method and 401 retry - [x] 2.1 Add generic `request` method to `src/haiiloClient.ts` - Accepts `{ method, path, params?, data? }` config - Calls `getAccessToken()`, makes request with Bearer token, returns `response.data` - _Requirements: 1.1, 1.2_ - [x] 2.2 Add Axios response interceptor for 401 retry - On 401: clear `accessToken`, re-authenticate, retry once using `_retried` flag - If retry also 401, propagate error - _Requirements: 1.3_ - [ ]* 2.3 Write property test for token caching (Property 5) - **Property 5: Token caching — single authentication per session** - Mock OAuth endpoint, make N requests, verify exactly 1 token request - **Validates: Requirements 1.1, 1.2** - [ ]* 2.4 Write property test for 401 retry logic (Property 10) - **Property 10: 401 retry — re-authenticate and retry once** - Mock API returning 401 then success, verify retry behavior and token refresh - **Validates: Requirements 1.3** - [ ]* 2.5 Write property test for missing credentials (Property 6) - **Property 6: Missing credentials produce error** - Generate arbitrary subsets of missing credentials, verify MCP error response - **Validates: Requirements 1.4** - [x] 3. Checkpoint — Ensure shared infrastructure tests pass - Ensure all tests pass, ask the user if questions arise. - [x] 4. Implement search tool registration module - [x] 4.1 Create `src/tools/searchTools.ts` with `registerSearchTools(server, client)` - Register `Search_FullText`: GET /api/search with query, page, pageSize params; return metadata only (id, title, type, excerpt, modified date) - Register `Search_QuickEntity`: GET /api/quick-entity-search with query param - Register `Search_Grouped`: GET /api/search/grouped with query param - All tools use Zod schemas with `.describe()` annotations and delegate errors to `handleApiError` - _Requirements: 3.1, 3.2, 3.3, 3.4, 3.5_ - [ ]* 4.2 Write property test for pagination forwarding (Property 2) - **Property 2: Pagination parameter forwarding** - Generate optional page/pageSize values, verify they are forwarded as query params when present and omitted when absent - **Validates: Requirements 3.2, 5.2, 6.4, 9.2** - [ ]* 4.3 Write property test for Search_FullText metadata only (Property 7) - **Property 7: Search_FullText returns metadata only** - Mock search response, verify result contains metadata fields and no full content - **Validates: Requirements 3.5** - [x] 5. Implement workspace tool registration module - [x] 5.1 Create `src/tools/workspaceTools.ts` with `registerWorkspaceTools(server, client)` - Register `Workspace_List`: GET /api/workspaces - Register `Workspace_Get`: GET /api/workspaces/{id} - Register `Workspace_GetMembers`: GET /api/workspaces/{id}/members - Register `Workspace_Join`: PUT /api/workspaces/{id}/members/join - Register `Workspace_Create`: POST /api/workspaces with name, description - _Requirements: 4.1, 4.2, 4.3, 4.4, 4.5_ - [x] 6. Implement news, people, and event tool registration modules - [x] 6.1 Create `src/tools/newsTools.ts` with `registerNewsTools(server, client)` - Register `News_GetFeed`: GET /web/blog/newsfeed with optional page, pageSize - _Requirements: 5.1, 5.2, 5.3_ - [x] 6.2 Create `src/tools/peopleTools.ts` with `registerPeopleTools(server, client)` - Register `People_GetMe`: GET /api/users/me - Register `People_List`: GET /api/users with optional page, pageSize - Register `People_Search`: GET /api/users/chooser/search with query - _Requirements: 6.1, 6.2, 6.3, 6.4_ - [x] 6.3 Create `src/tools/eventTools.ts` with `registerEventTools(server, client)` - Register `Event_Get`: GET /api/events/{id} - Register `Event_GetMemberships`: GET /api/events/{id}/memberships - Register `Event_UpdateStatus`: PUT /api/events/{id}/memberships/status with id, status - Register `Event_Create`: POST /api/events with title, description, startDate, endDate, location - _Requirements: 7.1, 7.2, 7.3, 7.4_ - [x] 7. Implement social, notification, and page tool registration modules - [x] 7.1 Create `src/tools/socialTools.ts` with `registerSocialTools(server, client)` - Register `Social_GetComments`: GET /api/comments with targetId - Register `Social_PostComment`: POST /api/comments with targetId, body - Register `Social_GetLikes`: GET /api/like-targets/{targetType}/{targetId} - Register `Social_ToggleLike`: POST /api/like-targets/{targetType}/{targetId}/likes/{userId} - _Requirements: 8.1, 8.2, 8.3, 8.4_ - [x] 7.2 Create `src/tools/notificationTools.ts` with `registerNotificationTools(server, client)` - Register `Notification_List`: GET /api/notifications with optional page, pageSize - Register `Notification_GetStatus`: GET /api/notifications/status - Register `Notification_MarkSeen`: PUT /api/notifications/mark-seen - _Requirements: 9.1, 9.2, 9.3, 9.4_ - [x] 7.3 Create `src/tools/pageTools.ts` with `registerPageTools(server, client)` - Register `Page_List`: GET /api/pages - Register `Page_Get`: GET /api/pages/{id} - Register `Page_GetMembers`: GET /api/pages/{id}/members - Register `Page_Create`: POST /api/pages with title, content - _Requirements: 10.1, 10.2, 10.3, 10.4_ - [x] 8. Implement content fetching tool registration module - [x] 8.1 Create `src/tools/contentTools.ts` with `registerContentTools(server, client)` - Register `Content_GetFull`: uses existing `getContentByType`, `fetchWidgetContent`, `extractTextFromWidgets`, `cleanHtml` logic from HaiiloClient - Accept contentId, contentType, optional appId, optional slug - Support blog-article, wiki-article, page, workspace, app, timeline-item - Return clean text extracted from widget HTML - Return error for unsupported content types - _Requirements: 11.1, 11.2, 11.3, 11.4, 11.5_ - [ ]* 8.2 Write property test for HTML widget text extraction (Property 8) - **Property 8: HTML widget text extraction removes all tags** - Generate arbitrary HTML strings, verify output contains no `<...>` sequences and entities are decoded - **Validates: Requirements 11.3** - [ ]* 8.3 Write property test for unsupported content type (Property 9) - **Property 9: Unsupported content type returns error** - Generate arbitrary strings not in the supported set, verify MCP error response - **Validates: Requirements 11.4** - [ ] 9. Checkpoint — Ensure all tool module tests pass - Ensure all tests pass, ask the user if questions arise. - [x] 10. Wire everything together and update server entry point - [x] 10.1 Create `src/tools/index.ts` barrel with `registerAllTools(server, client)` - Import and call all 9 registration functions in order - _Requirements: 2.1, 2.2_ - [x] 10.2 Update `src/getToolServer.ts` to use new architecture - Create one `HaiiloClient` instance per session (not per tool call) - Call `registerAllTools(server, client)` instead of `registerHaiiloTools` - Remove old import of `registerHaiiloTools` - _Requirements: 1.1, 2.2_ - [x] 10.3 Remove old `src/tools/haiiloTools.ts` - Delete the monolithic tool registration file - _Requirements: 2.1_ - [ ]* 10.4 Write property test for tool metadata completeness (Property 4) - **Property 4: Tool metadata completeness** - Instantiate McpServer, register all tools, verify each tool has `{Area}_{Action}` name pattern, non-empty description, and Zod schema - **Validates: Requirements 2.3, 2.4, 2.5** - [ ]* 10.5 Write property test for tool-to-endpoint routing (Property 1) - **Property 1: Tool-to-endpoint routing correctness** - For each registered tool with arbitrary valid input, mock `client.request`, invoke tool, verify correct HTTP method and path - **Validates: Requirements 3.1, 3.3, 3.4, 4.1–4.5, 5.1, 6.1–6.3, 7.1–7.4, 8.1–8.4, 9.1, 9.3, 9.4, 10.1–10.4, 11.1** - [ ] 11. Verify backward compatibility - [ ] 11.1 Verify `server.ts` is unchanged - Confirm StreamableHTTP transport on `/servers/dbplanet/mcp`, credentials via `x-dbplanet-*` headers, port 3000, `/health` endpoint - _Requirements: 13.1, 13.2, 13.3, 13.4_ - [ ]* 11.2 Write unit tests for backward compatibility - Test that server listens on port 3000, /health returns 200, all 28 tools are registered - _Requirements: 13.1, 13.2, 13.3, 13.4, 2.2_ - [ ] 12. Final checkpoint — Ensure all tests pass - Ensure all tests pass, ask the user if questions arise. ## Notes - Tasks marked with `*` are optional and can be skipped for faster MVP - Each task references specific requirements for traceability - Property tests validate universal correctness properties from the design document - The existing `server.ts` should remain unchanged — only `getToolServer.ts` and `src/tools/` are modified - The `HaiiloClient` content-fetching methods (`getContentByType`, `fetchWidgetContent`, `extractTextFromWidgets`, `cleanHtml`) need to be made accessible (public or package-internal) for use by `contentTools.ts`