Class McpMetricsExporter

java.lang.Object
com.mcpdbwizard.pub.McpMetricsExporter
All Implemented Interfaces:
AutoCloseable

public final class McpMetricsExporter extends Object implements AutoCloseable
Serves a McpMetrics registry at /metrics for Prometheus to scrape.
Environment
MCP_METRICS_PORT Port to listen on. Unset means no listener — see below.
MCP_METRICS_HOST Address to bind, default "127.0.0.1".

Why there is no default port

Generation-time PROMETHEUS_SERVER=YES emits this; the environment variable is what starts it. The same split as MCP_HTTP_TOKEN, and here it is not merely tidy: the web application launches up to twenty generated servers at once and the start-up harness forks twenty-one per box. A default port would give one of them a listener and the other twenty a bind failure to log, every run.

It uses the JDK's own HTTP server, and it is a separate port on purpose

com.sun.net.httpserver costs no dependency and works identically under both MCP transports — a stdio server has no Jetty to hang a servlet on, and stdio is where a locally-run server lives. A separate port also keeps the scrape off /mcp/*, whose bearer-token and Origin filters exist to guard a surface that can write, and which a Prometheus scraper would not satisfy anyway.

Exposure warns rather than refuses

Binding a non-loopback address logs a warning. It does not refuse the way McpHttpPolicy refuses an unauthenticated MCP port: this endpoint is read-only and carries no data from the database. It does publish the schema's object names and the shape of the traffic, which is worth a line in the log and worth a network policy, but it is not the same risk as an open call surface.

A failure here must not take the server down

An unusable port is reported and the MCP server carries on. Metrics are an observability sideline, and refusing to serve tools because nothing could be told about them would be the wrong trade — unlike the fail-closed security guards, where refusing IS the protection. A port that will not parse is different and does throw: that is an operator typo, and silently ignoring it leaves someone believing they are collecting metrics when they are not. Copyright 2003-2026 ATB Consultancy Services Ltd (formerly Orinda Software Ltd, Dublin, Ireland)

  • Field Details

  • Method Details

    • startIfConfigured

      public static McpMetricsExporter startIfConfigured(McpMetrics theMetrics, LogInterface theLog)
      Start the exporter if PORT_VARIABLE names a port, otherwise do nothing.
      Parameters:
      theMetrics - the registry to serve
      theLog - where a bind failure or an exposure warning is reported; may be null
      Returns:
      the running exporter, or null when no port was configured or the port could not be bound
      Throws:
      IllegalArgumentException - if the port or host setting cannot be understood
    • start

      public static McpMetricsExporter start(McpMetrics theMetrics, String theHost, int thePort) throws IOException
      Start an exporter on a given address, bypassing the environment.
      Parameters:
      thePort - the port, or 0 to let the operating system choose one
      Throws:
      IOException
    • getPort

      public int getPort()
      The port actually bound — the point of the exercise when 0 was requested.
    • close

      public void close()
      Specified by:
      close in interface AutoCloseable