From 63c407e128a0b078149413c558cc1dc9a32c5350 Mon Sep 17 00:00:00 2001 From: gusanthiago Date: Sat, 20 Jun 2026 23:23:02 -0300 Subject: [PATCH 1/2] docs: add documentation about health check in README.md --- README.md | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/README.md b/README.md index e706493be..9cdca1021 100644 --- a/README.md +++ b/README.md @@ -591,6 +591,44 @@ List of available preview features: - `mcpUI` - Enables an optional web-based UI for interacting with the MCP server. +#### Monitoring Server (Health Check & Metrics) + +When running with `--transport http`, you can expose a separate monitoring HTTP server for health checks and metrics. This server is only started when both `monitoringServerHost` and `monitoringServerPort` are set, and it listens on its own host/port (independent from the main `httpHost`/`httpPort`). + +The features exposed are controlled by `monitoringServerFeatures` (default: `health-check`). Available features and their endpoints: + +| Feature | Endpoint | Description | +| -------------- | ---------- | ------------------------------------------------------------------------------------------- | +| `health-check` | `/health` | Returns `200 OK` with a JSON body describing the server status. Useful for liveness probes. | +| `metrics` | `/metrics` | Returns server metrics in Prometheus text format. | + +The `/health` response is sent with `Cache-Control: no-store` and has the following shape (`status` is always `"ok"` while the process is alive): + +```json +{ + "status": "ok", + "version": "1.13.0", + "uptimeSeconds": 42, + "timestamp": "2026-06-20T12:00:00.000Z" +} +``` + +Example: start the server with the monitoring server enabled and call the health-check endpoint: + +```shell +npx -y mongodb-mcp-server@latest --transport http --httpHost 0.0.0.0 --httpPort 3000 --monitoringServerHost 0.0.0.0 --monitoringServerPort 8080 & +curl http://0.0.0.0:8080/health +# => {"status":"ok"} +``` + +To expose both endpoints, pass the features explicitly: + +```shell +npx -y mongodb-mcp-server@latest --transport http --monitoringServerHost 0.0.0.0 --monitoringServerPort 8080 --monitoringServerFeatures health-check,metrics +``` + +> **💡 Note:** `healthCheckHost` / `healthCheckPort` are deprecated aliases for `monitoringServerHost` / `monitoringServerPort` and continue to serve the same `/health` endpoint. + ### Atlas API Access To use the Atlas API tools, you'll need to create a service account in MongoDB Atlas: From 886f0f5c472be9269d4fc74459fe5eaf74649e99 Mon Sep 17 00:00:00 2001 From: gusanthiago Date: Sat, 20 Jun 2026 23:23:57 -0300 Subject: [PATCH 2/2] feat: enrich health-check response --- src/transports/monitoringServer.ts | 10 +++++++++- tests/unit/transports/monitoringServer.test.ts | 17 ++++++++++++++--- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/transports/monitoringServer.ts b/src/transports/monitoringServer.ts index a980012c4..a686854cb 100644 --- a/src/transports/monitoringServer.ts +++ b/src/transports/monitoringServer.ts @@ -1,5 +1,6 @@ import type express from "express"; import { LogId } from "../common/logging/loggingDefinitions.js"; +import { packageInfo } from "../common/packageInfo.js"; import type { DefaultMetrics, MonitoringServerFeature, @@ -53,7 +54,14 @@ export class MonitoringServer protected override setupRoutes(): Promise { if (this.features.includes("health-check")) { this.app.get("/health", (_req: express.Request, res: express.Response) => { - res.json({ status: "ok" }); + // Health responses should never be cached by proxies or load balancers. + res.set("Cache-Control", "no-store"); + res.json({ + status: "ok", + version: packageInfo.version, + uptimeSeconds: Math.floor(process.uptime()), + timestamp: new Date().toISOString(), + }); }); } diff --git a/tests/unit/transports/monitoringServer.test.ts b/tests/unit/transports/monitoringServer.test.ts index 36b27a643..a453136a3 100644 --- a/tests/unit/transports/monitoringServer.test.ts +++ b/tests/unit/transports/monitoringServer.test.ts @@ -47,9 +47,20 @@ describe("MonitoringServer", () => { const response = await fetch(`${server.serverAddress}/health`); expect(response.status).toBe(200); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const body = await response.json(); - expect(body).toEqual({ status: "ok" }); + expect(response.headers.get("cache-control")).toBe("no-store"); + const body = (await response.json()) as { + status: string; + version: string; + uptimeSeconds: number; + timestamp: string; + }; + // status remains "ok" for backward compatibility with existing probes + expect(body.status).toBe("ok"); + expect(typeof body.version).toBe("string"); + expect(typeof body.uptimeSeconds).toBe("number"); + expect(body.uptimeSeconds).toBeGreaterThanOrEqual(0); + // timestamp is a valid ISO date string + expect(Number.isNaN(Date.parse(body.timestamp))).toBe(false); }); it("does not expose health endpoint when health-check feature is disabled", async () => {