Input: Design documents from /specs/013-structured-server-state/
Prerequisites: plan.md, spec.md, research.md, data-model.md, contracts/
Tests: Not explicitly requested - test tasks included for critical areas only.
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
- Backend:
internal/for Go packages,cmd/mcpproxy/for CLI - Frontend:
frontend/src/for Vue components
Purpose: Add new health action constants and extend calculator input
- T001 [P] Add ActionSetSecret and ActionConfigure constants in internal/health/constants.go
- T002 [P] Add MissingSecret and OAuthConfigErr fields to HealthCalculatorInput in internal/health/calculator.go
Checkpoint: Constants and types ready for implementation ✅
Purpose: Core health calculation that MUST be complete before user stories can be tested
CRITICAL: No UI/CLI changes make sense until Health correctly detects issues
- T003 Add missing secret detection check to CalculateHealth() in internal/health/calculator.go
- T004 Add OAuth config error detection check to CalculateHealth() in internal/health/calculator.go
- T005 Add helper functions to extract MissingSecret from connection errors in internal/health/calculator.go
- T006 Add helper functions to extract OAuthConfigErr from connection errors in internal/health/calculator.go
- T007 Populate MissingSecret and OAuthConfigErr in HealthCalculatorInput within internal/runtime/runtime.go and internal/server/mcp.go
- T008 [P] Add unit tests for set_secret action in internal/health/calculator_test.go
- T009 [P] Add unit tests for configure action in internal/health/calculator_test.go
Checkpoint: Health correctly detects and reports new action types ✅
Goal: When user sees a health issue and clicks "Fix", they navigate to the correct location to resolve it
Independent Test:
- Configure a server with missing secret reference (e.g.,
${env:MISSING_TOKEN}) - Start mcpproxy and verify Health shows
action: "set_secret"withdetail: "MISSING_TOKEN" - Click "Set Secret" button in Web UI and verify navigation to
/secrets
- T010 [US1] Add set_secret action handler in frontend/src/components/ServerCard.vue
- T011 [US1] Add configure action handler in frontend/src/components/ServerCard.vue
- T012 [US1] Add button labels for new actions (set_secret, configure) in frontend/src/components/ServerCard.vue
- T013 [US1] Update TypeScript Server/Health types to include new action values in frontend/src/types/api.ts
Checkpoint: User Story 1 complete - Fix buttons navigate to correct pages ✅
Goal: mcpproxy doctor and Web UI show identical issues because both derive from Health
Independent Test:
- Configure server with missing secret
- Run
mcpproxy upstream listand verify showsset_secretaction hint - Run
mcpproxy doctorand verify missing secret appears in diagnostics - Compare with Web UI Dashboard - should show same affected servers
- T014 [US2] Add set_secret action hint formatting in cmd/mcpproxy/upstream_cmd.go outputServers()
- T015 [US2] Add configure action hint formatting in cmd/mcpproxy/upstream_cmd.go outputServers()
- T016 [US2] Refactor Doctor() to aggregate from Health.Action instead of independent detection in internal/management/diagnostics.go
- T017 [US2] Implement set_secret aggregation by secret name (cross-cutting) in internal/management/diagnostics.go
- T018 [US2] Update diagnostics_test.go to verify aggregation from Health in internal/management/diagnostics_test.go
Checkpoint: User Story 2 complete - CLI and Web UI show identical issues ✅
Goal: Dashboard displays ONE consolidated health section instead of duplicate banners
Independent Test:
- Configure servers with various issues (connection error, missing secret, OAuth needed)
- View Dashboard and verify only ONE "Servers Needing Attention" section appears
- Verify all issues are represented with correct action buttons
- T019 [US3] Remove "System Diagnostics" banner from frontend/src/views/Dashboard.vue
- T020 [US3] Ensure "Servers Needing Attention" section handles all action types in frontend/src/views/Dashboard.vue
- T021 [US3] Verify action buttons display correctly for set_secret and configure in Dashboard
Checkpoint: User Story 3 complete - Single consolidated health display ✅
Purpose: Verification and documentation
- T022 Run go test ./internal/health/... -v to verify all health tests pass
- T023 Run go test ./internal/management/... -v to verify diagnostics tests pass
- T024 Run ./scripts/test-api-e2e.sh for E2E verification
- T025 Run frontend build (cd frontend && npm run build) to verify no TypeScript errors
- T026 Update oas/swagger.yaml to document new action enum values (set_secret, configure)
Checkpoint: All verification passed ✅
Purpose: Address gaps discovered during output review vs spec/plan
Problem: Servers needing OAuth login (health action=login) appear under "Upstream Server Connection Errors" with generic remediation hints, not under "OAuth Authentication Required" with specific auth login hints.
Root Cause: The doctor_cmd.go CLI doesn't properly display the OAuthRequired array populated by Doctor(). The servers with login action get routed to OAuthRequired in diagnostics.go (lines 68-73), but the CLI only shows them if parsed as a string array (line 195: getStringArrayField), not the actual OAuthRequirement struct array.
- T027 [US2] Fix doctor_cmd.go to display OAuthRequired array as objects (server_name, message) not string array
- T028 [US2] Update doctor remediation for OAuth to show server-specific auth login commands
Problem: The ACTION column shows auth login --server=gcal but this isn't a runnable command - users need to know which binary to run (e.g., ./mcpproxy auth login --server=gcal or mcpproxy auth login --server=gcal).
Spec Reference: The spec table shows "CLI Hint" as auth login --server=X, but users expect copy-paste-able commands.
- T029 [US2] Update upstream_cmd.go to show full runnable command (matches spec format:
auth login --server=X)
Problem: The "Remediation" section shows generic hints for all upstream errors:
💡 Remediation:
• Check server configuration in mcp_config.json
• View detailed logs: mcpproxy upstream logs <server-name>
• Restart server: mcpproxy upstream restart <server-name>
But spec says remediation should be derived from Health.Action. For login action servers, it should say "Run: mcpproxy auth login --server=".
- T030 [US2] Fixed by properly routing servers to correct diagnostic categories (OAuth→oauth_required, errors→upstream_errors)
Checkpoint: All gaps addressed ✅
Goal: Tray menu uses health.* fields as single source of truth, not legacy fields or URL heuristics
Independent Test:
- Configure a stdio OAuth server (e.g.,
npx @anthropic/mcp-gcal) that needs login - View tray menu and verify "
⚠️ Login Required" appears (not just generic options) - Verify tray connected count matches Web UI count
Tray Status Display (FR-013, FR-016, FR-017):
- T031 [US4] Remove
serverSupportsOAuth()URL heuristic function from internal/tray/managers.go - T032 [US4] Update
getServerStatusDisplay()to usehealth.levelinstead of legacyconnectedfield in internal/tray/managers.go - T033 [US4] Update
getServerStatusDisplay()to usehealth.summaryfor status text in internal/tray/managers.go - T034 [US4] Update tooltip generation to use
health.detailinstead oflast_errorin internal/tray/managers.go
Tray Action Menus (FR-014, FR-015):
- T035 [US4] Update
createServerActionSubmenus()to show actions based onhealth.actionin internal/tray/managers.go - T036 [US4] Add "
⚠️ Login Required" menu item whenhealth.action == "login"(no URL check) in internal/tray/managers.go - T037 [US4] Add "
⚠️ Set Secret" menu item whenhealth.action == "set_secret"in internal/tray/managers.go - T038 [US4] Add "
⚠️ Configure" menu item whenhealth.action == "configure"in internal/tray/managers.go
Tray Connected Count (FR-013):
- T039 [US4] Update connected server count logic to use
health.level == "healthy"only in internal/tray/managers.go - T040 [US4] Remove fallback to legacy
connectedfield in connected count calculation in internal/tray/managers.go
Tests:
- T041 [US4] [P] Add unit tests for tray menu showing login action for stdio servers in internal/tray/managers_test.go
- T042 [US4] [P] Add unit tests for tray connected count using health.level in internal/tray/managers_test.go
Checkpoint: User Story 4 complete - Tray uses health data as single source of truth ✅
Goal: Web UI suppresses redundant last_error display when health.action already conveys the issue
Independent Test:
- Configure a server that needs OAuth login
- View server in Web UI and verify only "Login" button appears, not verbose error message
- Configure a server with missing secret, verify only "Set Secret" button appears
Error Display Suppression (FR-018, FR-019):
- T043 [US5] Update ServerCard.vue to suppress
last_errordisplay whenhealth.actionisloginin frontend/src/components/ServerCard.vue - T044 [US5] Update ServerCard.vue to suppress
last_errordisplay whenhealth.actionisset_secretin frontend/src/components/ServerCard.vue - T045 [US5] Update ServerCard.vue to suppress
last_errordisplay whenhealth.actionisconfigurein frontend/src/components/ServerCard.vue - T046 [US5] Add computed property
shouldShowErrorthat checks if error is redundant with health action in frontend/src/components/ServerCard.vue
Checkpoint: User Story 5 complete - Web UI shows clean, non-redundant error states ✅
- Setup (Phase 1): No dependencies - can start immediately
- Foundational (Phase 2): Depends on Setup completion - BLOCKS all user stories
- User Stories (Phase 3-5): All depend on Foundational phase completion
- US1 and US2 are both P1 priority but work on different layers (UI vs CLI/Backend)
- US3 is P2 and depends on Doctor refactor from US2 for proper data flow
- Polish (Phase 6): Depends on all user stories being complete
- User Story 4 (Phase 8): Depends on Foundational - Tray-focused, can run in parallel with US1/US2
- User Story 5 (Phase 9): Depends on Foundational - Frontend-focused, can run in parallel with US4
- User Story 1 (P1): Can start after Foundational - Frontend-focused
- User Story 2 (P1): Can start after Foundational - Backend/CLI-focused
- User Story 3 (P2): Best after US2 since Dashboard needs proper Health-aggregated data
- User Story 4 (P1): Can start after Foundational - Tray-focused (internal/tray/)
- User Story 5 (P2): Can start after Foundational - Frontend-focused (ServerCard.vue)
- Health detection must work (Foundational) before UI/CLI can surface actions
- Backend changes before frontend changes that depend on them
- Story complete before moving to next priority
Phase 1 (all parallel):
- T001 and T002 can run in parallel (different files)
Phase 2 (sequential core, parallel tests):
- T003-T007 are sequential (dependency chain)
- T008 and T009 can run in parallel (different test cases)
User Stories (can overlap):
- US1 (T010-T013) and US2 (T014-T018) can run in parallel (different files)
- US3 (T019-T021) should wait for US2 for best results
- US4 (T031-T042) can run in parallel with US1/US2 (different directory: internal/tray/)
- US5 (T043-T046) can run in parallel with US4 (same file as US1 but different section)
# After Foundational phase completes, launch user stories in parallel:
# User Story 1 - Frontend (ServerCard actions):
Task: "[US1] Add set_secret action handler in frontend/src/components/ServerCard.vue"
Task: "[US1] Add configure action handler in frontend/src/components/ServerCard.vue"
# User Story 2 - Backend/CLI:
Task: "[US2] Add set_secret action hint formatting in cmd/mcpproxy/upstream_cmd.go"
Task: "[US2] Refactor Doctor() to aggregate from Health in internal/management/diagnostics.go"
# User Story 4 - Tray (can run in parallel - different directory):
Task: "[US4] Remove serverSupportsOAuth() URL heuristic function from internal/tray/managers.go"
Task: "[US4] Update createServerActionSubmenus() to show actions based on health.action"- Complete Phase 1: Setup (constants and types)
- Complete Phase 2: Foundational (detection logic)
- Complete Phase 3: User Story 1 (Fix buttons navigate correctly)
- Complete Phase 4: User Story 2 (CLI and Web UI consistent)
- Complete Phase 8: User Story 4 (Tray uses health data)
- STOP and VALIDATE: All P1 stories should work
- Deploy/demo if ready
- Complete Setup + Foundational -> Detection works
- Add User Story 1 -> Fix buttons work -> Demo
- Add User Story 2 -> CLI consistency -> Demo
- Add User Story 4 -> Tray consistency -> Demo
- Add User Story 3 -> Single banner -> Demo
- Add User Story 5 -> Clean error states -> Demo
- Each story adds value without breaking previous stories
- [P] tasks = different files, no dependencies
- [Story] label maps task to specific user story for traceability
- US1 and US2 are both P1 but target different layers (can be parallel)
- Foundational phase is critical - Health detection must work before anything else makes sense
- Verify existing tests still pass after each phase