Input: Design documents from /specs/021-request-id-logging/
Prerequisites: plan.md (required), spec.md (required), research.md, data-model.md, contracts/
Tests: Tests are included as this feature touches critical error handling paths.
Organization: Tasks are grouped by user story to enable independent implementation and testing of each story.
- [P]: Can run in parallel (different files, no dependencies)
- [Story]: Which user story this task belongs to (e.g., US1, US2, US3)
- Include exact file paths in descriptions
- CLI:
cmd/mcpproxy/ - HTTP API:
internal/httpapi/ - Server:
internal/server/ - Request Context:
internal/reqcontext/ - Contracts:
internal/contracts/ - Tests:
internal/server/e2e_test.go,internal/httpapi/*_test.go
Purpose: Extend existing request context infrastructure for request IDs
- T001 [P] Add RequestID constants and helpers to
internal/reqcontext/correlation.go - T002 [P] Add request ID validation helper function in
internal/reqcontext/requestid.go(new file) - T003 Add unit tests for request ID validation in
internal/reqcontext/requestid_test.go
Purpose: Core middleware and error response infrastructure that ALL user stories depend on
CRITICAL: No user story work can begin until this phase is complete
- T004 Create RequestID middleware in
internal/httpapi/middleware.go(new file)- Generate UUID v4 if
X-Request-Idheader missing or invalid - Validate client-provided IDs against pattern
^[a-zA-Z0-9_-]{1,256}$ - Set
X-Request-Idresponse header BEFORE calling next handler - Add request ID to context using
reqcontextpackage
- Generate UUID v4 if
- T005 [P] Extend
contracts.ErrorResponseininternal/contracts/types.goto includerequest_idfield - T006 [P] Update
contracts.NewErrorResponse()ininternal/contracts/converters.goto accept and include request_id - T007 Update
Server.writeError()ininternal/httpapi/server.goto extract request ID from context and include in response - T008 Register RequestID middleware FIRST in router chain in
internal/server/server.go - T009 Add request ID to Zap logger context in middleware for request-scoped logging
Checkpoint: Foundation ready - all API responses now include X-Request-Id header and error responses include request_id in body
Goal: Every error response includes a request_id field that users can use to find related logs.
Independent Test: Make any API call that returns an error and verify request_id in response body and X-Request-Id header.
- T010 [P] [US1] Add E2E test: verify X-Request-Id header in ALL responses in
internal/server/e2e_test.go - T011 [P] [US1] Add E2E test: verify request_id in error JSON body in
internal/server/e2e_test.go - T012 [P] [US1] Add E2E test: verify client-provided X-Request-Id is echoed back in
internal/server/e2e_test.go - T013 [P] [US1] Add E2E test: verify invalid X-Request-Id is replaced with generated UUID in
internal/server/e2e_test.go
- T014 [US1] Update all
writeError()calls ininternal/httpapi/server.goto use new signature (audit all ~100 calls) - T015 [US1] Update
writeError()ininternal/httpapi/activity.goto use new error response pattern - T016 [US1] Update
writeError()ininternal/httpapi/code_exec.goto use new error response pattern
Checkpoint: At this point, User Story 1 should be fully functional - all API errors include request_id
Goal: All log entries for a request include the request_id, enabling filtering.
Independent Test: Make a request with X-Request-Id, check daemon logs contain the ID.
- T017 [P] [US2] Add test: verify logs include request_id field when in request context in
internal/httpapi/handlers_test.go
- T018 [US2] Create logger-with-request-id helper in
internal/httpapi/middleware.go(Done in Phase 2) - T019 [US2] Update request handlers to use context-aware logger in
internal/httpapi/server.go(Added getRequestLogger helper) - T020 [US2] Ensure OAuth flows log both request_id and correlation_id in
internal/httpapi/middleware.go(Already implemented)
Checkpoint: At this point, all request-scoped logs include request_id for filtering
Goal: CLI displays the request ID on errors and suggests how to retrieve logs.
Independent Test: Run a CLI command that fails and verify Request ID is printed with log suggestion.
- T021 [P] [US3] Add test: CLI prints request_id on error in
cmd/mcpproxy/upstream_cmd_test.go - T022 [P] [US3] Add test: CLI does NOT print request_id on success in
cmd/mcpproxy/upstream_cmd_test.go
- T023 [US3] Create CLI error display helper that extracts and prints request_id in
cmd/mcpproxy/cmd_helpers.go - T024 [US3] Update
upstreamcommand error handling to display request ID incmd/mcpproxy/upstream_cmd.go - T025 [US3] Update
authcommand error handling to display request ID incmd/mcpproxy/auth_cmd.go - T026 [US3] Update
activitycommand error handling to display request ID incmd/mcpproxy/activity_cmd.go - T027 [US3] Update
toolscommand error handling to display request ID incmd/mcpproxy/tools_cmd.go - T028 [US3] Update
callcommand error handling to display request ID incmd/mcpproxy/call_cmd.go - T029 [US3] Update
codecommand error handling to display request ID incmd/mcpproxy/code_cmd.go
Checkpoint: At this point, CLI users see request_id on errors with log retrieval suggestion
Goal: Users can retrieve logs filtered by request ID.
Independent Test: Make request, get request ID from error, retrieve logs using that ID.
- T030 [P] [US4] Add E2E test:
--request-idflag filters activity logs ininternal/server/e2e_test.go - T031 [P] [US4] Add E2E test: API query param
request_idfilters logs ininternal/server/e2e_test.go
- T032 [US4] Extend ActivityRecord to include request_id field in
internal/contracts/activity.go - T033 [US4] Update activity recording to capture request_id from context in
internal/storage/activity.go - T034 [US4] Add
--request-idflag toactivity listcommand incmd/mcpproxy/activity_cmd.go - T035 [US4] Add
request_idquery parameter to activity API handler ininternal/httpapi/activity.go - T036 [US4] Update activity storage query to filter by request_id in
internal/storage/activity.go
Checkpoint: At this point, users can retrieve logs filtered by request_id via CLI and API
Purpose: Documentation, validation, and cleanup
- T037 [P] Update OpenAPI spec (
oas/swagger.yaml) with X-Request-Id header and error response schema - T038 [P] Update CLAUDE.md error handling documentation
- T039 Run
./scripts/test-api-e2e.shto verify all E2E tests pass - T040 Run
./scripts/verify-oas-coverage.shto ensure OpenAPI coverage - T041 Run quickstart.md validation - test all documented commands work
- T042 Run
./scripts/run-linter.shto ensure code quality
- Setup (Phase 1): No dependencies - can start immediately
- Foundational (Phase 2): Depends on Setup completion - BLOCKS all user stories
- User Stories (Phase 3-6): All depend on Foundational phase completion
- US1 (Phase 3) and US2 (Phase 4) can run in parallel
- US3 (Phase 5) depends on US1 (needs error response with request_id)
- US4 (Phase 6) can start after Foundational but benefits from US1/US2
- Polish (Phase 7): Depends on all user stories being complete
- User Story 1 (P1): Can start after Foundational (Phase 2) - No dependencies on other stories
- User Story 2 (P1): Can start after Foundational (Phase 2) - No dependencies on other stories
- User Story 3 (P2): Depends on US1 (error responses must include request_id first)
- User Story 4 (P2): Can start after Foundational (Phase 2) - Integrates with US1/US2
- Tests MUST be written and FAIL before implementation
- Infrastructure changes before handler updates
- Core implementation before integration
- Story complete before moving to next priority
Phase 1 (Setup):
# Can run in parallel:
T001: Add RequestID constants to reqcontext/correlation.go
T002: Add validation helper in reqcontext/requestid.goPhase 2 (Foundational):
# Can run in parallel:
T005: Extend ErrorResponse in contracts/types.go
T006: Update NewErrorResponse in contracts/converters.goPhase 3 (US1 Tests):
# All tests can run in parallel:
T010: E2E test for X-Request-Id header
T011: E2E test for request_id in error body
T012: E2E test for client-provided ID echo
T013: E2E test for invalid ID replacementPhase 5 (US3 Implementation):
# CLI command updates can run in parallel after T023:
T024: upstream_cmd.go
T025: auth_cmd.go
T026: activity_cmd.go
T027: tools_cmd.go
T028: call_cmd.go
T029: code_cmd.go# After Foundational phase completes:
# Launch all US1 tests together (should FAIL initially):
Task T010: "E2E test: verify X-Request-Id header in ALL responses"
Task T011: "E2E test: verify request_id in error JSON body"
Task T012: "E2E test: verify client-provided X-Request-Id is echoed"
Task T013: "E2E test: verify invalid X-Request-Id is replaced"
# Then implement sequentially:
Task T014: "Update writeError() calls in httpapi/server.go"
Task T015: "Update writeError() in httpapi/activity.go"
Task T016: "Update writeError() in httpapi/code_exec.go"
# Verify tests now PASS- Complete Phase 1: Setup (T001-T003)
- Complete Phase 2: Foundational (T004-T009)
- Complete Phase 3: User Story 1 (T010-T016)
- STOP and VALIDATE: All API errors include request_id
- Deploy/demo if ready
- Complete Setup + Foundational Foundation ready
- Add User Story 1 Test independently Deploy/Demo (MVP!)
- Add User Story 2 Request-scoped logging works
- Add User Story 3 CLI shows request_id on errors
- Add User Story 4 Log retrieval by request_id works
- Each story adds value without breaking previous stories
With multiple developers:
- Team completes Setup + Foundational together
- Once Foundational is done:
- Developer A: User Story 1 (error responses)
- Developer B: User Story 2 (logging)
- After US1 complete:
- Developer A: User Story 3 (CLI display)
- Developer B: User Story 4 (log retrieval)
- Stories complete and integrate independently
- [P] tasks = different files, no dependencies
- [Story] label maps task to specific user story for traceability
- Each user story should be independently completable and testable
- Verify tests fail before implementing
- Commit after each task or logical group
- Stop at any checkpoint to validate story independently
- User Story 5 (Tray/Web UI) is OUT OF SCOPE per spec - only server-side + CLI changes
| File | Changes |
|---|---|
internal/reqcontext/correlation.go |
Add RequestIDKey constant |
internal/reqcontext/requestid.go |
NEW: Validation helper |
internal/httpapi/middleware.go |
NEW: RequestID middleware |
internal/contracts/types.go |
Extend ErrorResponse |
internal/contracts/converters.go |
Update NewErrorResponse |
internal/httpapi/server.go |
Update writeError, register middleware |
internal/httpapi/activity.go |
Update error responses, add filter |
internal/httpapi/code_exec.go |
Update error responses |
internal/server/server.go |
Register middleware in router |
cmd/mcpproxy/cmd_helpers.go |
CLI error display helper |
cmd/mcpproxy/*_cmd.go |
Update error handling |
internal/contracts/activity.go |
Add request_id field |
internal/storage/activity.go |
Store/query request_id |
oas/swagger.yaml |
Document X-Request-Id header |