Skip to content

feat: add health check server implementation#76

Merged
Patrick-Ehimen merged 1 commit intomainfrom
feat/health-check
Feb 13, 2026
Merged

feat: add health check server implementation#76
Patrick-Ehimen merged 1 commit intomainfrom
feat/health-check

Conversation

@Patrick-Ehimen
Copy link
Owner

@Patrick-Ehimen Patrick-Ehimen commented Feb 13, 2026

  • Add HealthCheckServer class for server health monitoring
  • Implement health check types and utilities
  • Add comprehensive unit tests for health check functionality
  • Integrate health check endpoints into server configuration
  • Update main server to include health check initialization

Pull Request

Description

Type of change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation update
  • Other (describe):

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

Related Issues

Screenshots (if applicable)

Summary by Sourcery

Add a dedicated HTTP health check server exposing liveness and readiness endpoints and wire it into the MCP server lifecycle and configuration.

New Features:

  • Introduce a standalone HealthCheckServer that provides /health and /ready HTTP endpoints on a configurable port.
  • Add health check configuration to the server config with defaults and environment variable overrides.
  • Expose HealthCheckServer and health check types from the MCP server package and CLI, including a --health-port flag and related env vars.

Tests:

  • Add unit tests covering health and readiness endpoints, error handling, connectivity checking behavior, and HealthCheckServer lifecycle.

- Add HealthCheckServer class for server health monitoring
- Implement health check types and utilities
- Add comprehensive unit tests for health check functionality
- Integrate health check endpoints into server configuration
- Update main server to include health check initialization
@sourcery-ai
Copy link

sourcery-ai bot commented Feb 13, 2026

Reviewer's Guide

Implements a dedicated HTTP-based HealthCheckServer exposing /health and /ready endpoints on a configurable localhost port, wires it into the LighthouseMCPServer lifecycle and configuration, and adds tests plus CLI/env wiring for enabling and configuring health checks and Lighthouse API connectivity monitoring.

Sequence diagram for /ready health check request flow

sequenceDiagram
  actor Client
  participant HealthCheckServer
  participant AuthManager
  participant LighthouseServiceFactory
  participant ILighthouseService
  participant LighthouseAPI

  Client->>HealthCheckServer: GET /ready
  HealthCheckServer->>HealthCheckServer: handleRequest(req, res)
  HealthCheckServer->>HealthCheckServer: handleReady(res)

  HealthCheckServer->>HealthCheckServer: checkSDK()
  HealthCheckServer->>ILighthouseService: getStorageStats()
  ILighthouseService-->>HealthCheckServer: storageStats
  HealthCheckServer-->>HealthCheckServer: sdkCheck

  HealthCheckServer->>HealthCheckServer: checkCache()
  HealthCheckServer->>AuthManager: getCacheStats()
  AuthManager-->>HealthCheckServer: cacheStats
  HealthCheckServer-->>HealthCheckServer: cacheCheck

  HealthCheckServer->>HealthCheckServer: checkServicePool()
  HealthCheckServer->>LighthouseServiceFactory: getStats()
  LighthouseServiceFactory-->>HealthCheckServer: poolStats
  HealthCheckServer-->>HealthCheckServer: poolCheck

  HealthCheckServer->>HealthCheckServer: checkLighthouseConnectivity()
  alt recent_cached_result
    HealthCheckServer-->>HealthCheckServer: use lastConnectivityCheck
  else needs_fresh_check
    HealthCheckServer->>LighthouseAPI: HTTPS GET /api/lighthouse/file_info
    LighthouseAPI-->>HealthCheckServer: response
    HealthCheckServer-->>HealthCheckServer: update lastConnectivityCheck
  end

  HealthCheckServer-->>HealthCheckServer: connectivityCheck

  HealthCheckServer-->>HealthCheckServer: aggregate checks into ReadinessStatus
  alt all checks up
    HealthCheckServer-->>Client: 200 ReadinessStatus status=ready
  else any check down
    HealthCheckServer-->>Client: 503 ReadinessStatus status=not_ready
  end
Loading

Class diagram for HealthCheckServer and health check types

classDiagram
  class LighthouseMCPServer {
    -Server server
    -ServerConfig config
    -AuthManager authManager
    -LighthouseServiceFactory serviceFactory
    -ILighthouseService lighthouseService
    -ToolRegistry registry
    -Logger logger
    -HealthCheckServer healthServer
    +start(): Promise<void>
    +stop(): Promise<void>
  }

  class HealthCheckServer {
    -http.Server httpServer
    -number startTime
    -HealthCheckDependencies deps
    -HealthCheckConfig healthConfig
    -Logger logger
    -lastConnectivityCheck lastConnectivityCheck
    +HealthCheckServer(deps: HealthCheckDependencies, healthConfig: HealthCheckConfig)
    +start(): Promise<void>
    +stop(): Promise<void>
    +getPort(): number
    +checkLighthouseConnectivity(): Promise<ReadinessCheck>
    -handleRequest(req: http.IncomingMessage, res: http.ServerResponse): void
    -handleHealth(res: http.ServerResponse): void
    -handleReady(res: http.ServerResponse): Promise<void>
    -checkSDK(): ReadinessCheck
    -checkCache(): ReadinessCheck
    -checkServicePool(): ReadinessCheck
    -pingLighthouseApi(apiUrl: string, timeout: number): Promise<number>
    -sendJSON(res: http.ServerResponse, statusCode: number, body: unknown): void
  }

  class HealthCheckDependencies {
    +AuthManager authManager
    +LighthouseServiceFactory serviceFactory
    +ILighthouseService lighthouseService
    +ToolRegistry registry
    +ServerConfig config
    +Logger logger
  }

  class HealthCheckConfig {
    +boolean enabled
    +number port
    +string lighthouseApiUrl
    +number connectivityCheckInterval
    +number connectivityTimeout
  }

  class HealthStatus {
    +string status
    +string timestamp
    +number uptime
    +string version
  }

  class ReadinessCheck {
    +string status
  }

  class ReadinessStatus {
    +string status
    +string timestamp
    +ReadinessCheck sdk
    +ReadinessCheck cache
    +ReadinessCheck lighthouse_api
    +ReadinessCheck service_pool
  }

  class ServerConfig {
    +HealthCheckConfig healthCheck
  }

  class AuthManager {
    +getCacheStats(): unknown
  }

  class LighthouseServiceFactory {
    +getStats(): unknown
  }

  class ILighthouseService {
    +getStorageStats(): unknown
  }

  class ToolRegistry
  class Logger {
    +info(message: string, meta: unknown): void
    +error(message: string, meta: unknown): void
  }

  LighthouseMCPServer --> HealthCheckServer : manages
  LighthouseMCPServer --> ServerConfig : uses
  LighthouseMCPServer --> AuthManager : uses
  LighthouseMCPServer --> LighthouseServiceFactory : uses
  LighthouseMCPServer --> ILighthouseService : uses
  LighthouseMCPServer --> ToolRegistry : uses
  LighthouseMCPServer --> Logger : uses

  HealthCheckServer --> HealthCheckDependencies : aggregates
  HealthCheckServer --> HealthCheckConfig : uses
  HealthCheckServer --> HealthStatus : returns
  HealthCheckServer --> ReadinessStatus : returns
  HealthCheckServer --> ReadinessCheck : returns

  HealthCheckDependencies --> AuthManager
  HealthCheckDependencies --> LighthouseServiceFactory
  HealthCheckDependencies --> ILighthouseService
  HealthCheckDependencies --> ToolRegistry
  HealthCheckDependencies --> ServerConfig
  HealthCheckDependencies --> Logger

  ServerConfig --> HealthCheckConfig
Loading

File-Level Changes

Change Details Files
Introduce standalone HealthCheckServer HTTP service with liveness/readiness endpoints and Lighthouse API connectivity checks.
  • Create HealthCheckServer that listens on a configurable localhost port, tracking start time and exposing getPort()
  • Implement /health endpoint returning JSON with status, version, uptime, and timestamp
  • Implement /ready endpoint aggregating SDK, auth cache, service pool, and Lighthouse API connectivity checks to determine readiness and HTTP 200 vs 503
  • Add internal checks for SDK (storage stats), auth cache (cache stats), and service pool (factory pool stats) with guarded error handling
  • Implement Lighthouse API connectivity check with HTTPS ping, timeout handling, and simple in-memory caching of last result
  • Add common JSON response helper to set headers and prevent caching
apps/mcp-server/src/health/HealthCheckServer.ts
Define health check configuration and response types and expose health check module from the package.
  • Add HealthCheckConfig, HealthStatus, ReadinessCheck, and ReadinessStatus interfaces for typed health check behavior
  • Create health module index to re-export HealthCheckServer, HealthCheckDependencies, and health types for external use
apps/mcp-server/src/health/types.ts
apps/mcp-server/src/health/index.ts
Wire health check configuration into server config defaults and environment-driven settings.
  • Extend ServerConfig to include an optional healthCheck section
  • Define DEFAULT_HEALTH_CHECK_CONFIG using HEALTH_CHECK_ENABLED, HEALTH_CHECK_PORT, and LIGHTHOUSE_API_URL env vars plus default timing values
  • Include healthCheck in getDefaultServerConfig and DEFAULT_SERVER_CONFIG
apps/mcp-server/src/config/server-config.ts
Integrate HealthCheckServer into LighthouseMCPServer startup/shutdown and public exports, and add CLI/env controls.
  • Add optional healthServer field to LighthouseMCPServer, creating and starting it when config.healthCheck.enabled is true and logging the health port
  • Ensure health server is stopped and cleared during LighthouseMCPServer.stop() lifecycle
  • Export HealthCheckServer from the top-level mcp-server index for consumers
  • Extend CLI usage text, environment variable docs, and argument parsing to support --health-port, HEALTH_CHECK_ENABLED, HEALTH_CHECK_PORT, and LIGHTHOUSE_API_URL, initializing config.healthCheck when needed
apps/mcp-server/src/server.ts
apps/mcp-server/src/index.ts
apps/mcp-server/src/config/server-config.ts
Add unit tests covering HealthCheckServer endpoints, lifecycle, and error handling.
  • Create Vitest suite standing up a real HealthCheckServer instance bound to an OS-assigned port and issuing HTTP requests to /health and /ready
  • Mock AuthManager, LighthouseServiceFactory, ILighthouseService, and ToolRegistry to provide deterministic stats for readiness checks
  • Verify /health response structure, uptime, and JSON content-type
  • Verify /ready readiness success path, inclusion of cache/service pool/Lighthouse latency details, and 503 behavior when SDK or Lighthouse connectivity checks fail
  • Test 404 behavior for unknown paths and root, port reporting, clean shutdown behavior, and behavior of getPort() before start
apps/mcp-server/src/__tests__/health-check.test.ts

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 2 issues, and left some high level feedback:

  • In pingLighthouseApi, you always use https.get and default to port 443, which will break if lighthouseApiUrl is configured with an http URL or a non-HTTPS custom port; consider selecting http vs https and the default port based on url.protocol.
  • When starting the health check server, the log message uses this.healthConfig.port, which will be 0 when an OS-assigned port is requested; it would be more accurate to log the actual bound port via this.httpServer.address() (and optionally update healthConfig.port).
  • In the CLI handling for --health-port, parseInt may return NaN for invalid input and will be passed through to the server; add validation and surface a clear error or fallback rather than allowing an invalid port to reach listen.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `pingLighthouseApi`, you always use `https.get` and default to port 443, which will break if `lighthouseApiUrl` is configured with an `http` URL or a non-HTTPS custom port; consider selecting `http` vs `https` and the default port based on `url.protocol`.
- When starting the health check server, the log message uses `this.healthConfig.port`, which will be `0` when an OS-assigned port is requested; it would be more accurate to log the actual bound port via `this.httpServer.address()` (and optionally update `healthConfig.port`).
- In the CLI handling for `--health-port`, `parseInt` may return `NaN` for invalid input and will be passed through to the server; add validation and surface a clear error or fallback rather than allowing an invalid port to reach `listen`.

## Individual Comments

### Comment 1
<location> `apps/mcp-server/src/index.ts:110` </location>
<code_context>
+            if (!config.healthCheck) {
+              config.healthCheck = { enabled: true, port: 8080 };
+            }
+            config.healthCheck.port = parseInt(args[i]!, 10);
+            config.healthCheck.enabled = true;
+          }
</code_context>

<issue_to_address>
**issue (bug_risk):** Validate and guard against invalid `--health-port` values to avoid `NaN` ports.

`parseInt` can return `NaN` or an out-of-range value, which will be passed directly to `HealthCheckServer.listen` and fail at runtime. Please validate the parsed value (e.g., `Number.isInteger(port)` and `0 < port && port < 65536`) and either fall back to the default or exit with a clear error if invalid.
</issue_to_address>

### Comment 2
<location> `apps/mcp-server/src/health/HealthCheckServer.ts:222-229` </location>
<code_context>
+      const start = Date.now();
+      const url = new URL("/api/lighthouse/file_info?cid=test", apiUrl);
+
+      const req = https.get(
+        {
+          hostname: url.hostname,
+          path: url.pathname + url.search,
+          port: url.port || 443,
+          timeout,
+        },
+        (res) => {
+          // Any response means the API is reachable
+          res.resume(); // Drain the response
</code_context>

<issue_to_address>
**issue (bug_risk):** Honor the protocol of `lighthouseApiUrl` instead of unconditionally using HTTPS.

`pingLighthouseApi` always calls `https.get`, so it will break if `healthConfig.lighthouseApiUrl` is `http://` (common for local/dev). Use `url.protocol` to choose `http.get` vs `https.get` (e.g. `url.protocol === "http:" ? http.get : https.get`) so the health check works for both HTTP and HTTPS endpoints.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

if (!config.healthCheck) {
config.healthCheck = { enabled: true, port: 8080 };
}
config.healthCheck.port = parseInt(args[i]!, 10);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Validate and guard against invalid --health-port values to avoid NaN ports.

parseInt can return NaN or an out-of-range value, which will be passed directly to HealthCheckServer.listen and fail at runtime. Please validate the parsed value (e.g., Number.isInteger(port) and 0 < port && port < 65536) and either fall back to the default or exit with a clear error if invalid.

Comment on lines +222 to +229
const req = https.get(
{
hostname: url.hostname,
path: url.pathname + url.search,
port: url.port || 443,
timeout,
},
(res) => {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Honor the protocol of lighthouseApiUrl instead of unconditionally using HTTPS.

pingLighthouseApi always calls https.get, so it will break if healthConfig.lighthouseApiUrl is http:// (common for local/dev). Use url.protocol to choose http.get vs https.get (e.g. url.protocol === "http:" ? http.get : https.get) so the health check works for both HTTP and HTTPS endpoints.

@Patrick-Ehimen Patrick-Ehimen merged commit 17c6d42 into main Feb 13, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant