Observability - Tracing and Metrics

This reference documents the observability capabilities provided by the Quarkus MCP Server extension, including distributed tracing through OpenTelemetry integration and metrics through Micrometer integration.

Tracing

The Quarkus MCP Server extension provides built-in distributed tracing when the Quarkus OpenTelemetry extension is present. The feature is disabled by default and must be explicitly enabled through configuration. The instrumentation follows the OpenTelemetry Semantic Conventions for MCP.

Traces are created for:

  • All MCP protocol method calls (tools, prompts, resources, etc.)

  • Notifications (notifications/initialized, notifications/roots/list_changed, etc.)

  • Server-to-client callbacks (sampling, elicitation)

Prerequisites

The following dependency must be present to enable tracing:

<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-opentelemetry</artifactId>
</dependency>

See the Quarkus OpenTelemetry guide and the Quarkus OpenTelemetry Tracing guide for general setup, exporter, sampler, and other configurations.

Configuration

Tracing is controlled by the following configuration property:

quarkus.mcp.server.tracing.enabled=true

Span Naming

Each MCP operation produces a SERVER span. The span name is the JSON-RPC method name, optionally followed by a resource identifier for specific operations:

Method Span Name

tools/call

tools/call <tool-name> (e.g., tools/call toLowerCase)

prompts/get

prompts/get <prompt-name> (e.g., prompts/get code_assist)

resources/read

resources/read

resources/subscribe

resources/subscribe

resources/unsubscribe

resources/unsubscribe

All other methods

The JSON-RPC method name (e.g., initialize, tools/list, ping)

Span Attributes

Common Attributes

All MCP spans include the following attributes:

Attribute Description

mcp.method.name

The JSON-RPC method name (e.g., tools/call, prompts/get)

mcp.session.id

The MCP connection/session identifier

mcp.protocol.version

The negotiated MCP protocol version (not available during initialize)

rpc.jsonrpc.request_id

The JSON-RPC request ID (only for requests, not for notifications)

network.transport

tcp for HTTP/WebSocket, pipe for stdio

network.protocol.name

http for HTTP transport (null for stdio)

network.protocol.version

2 for Streamable HTTP (null for WebSocket and stdio)

Method-Specific Attributes

Some methods add additional attributes:

Method Attribute Description

tools/call

gen_ai.tool.name

The name of the tool being called

tools/call

gen_ai.operation.name

Always set to execute_tool

prompts/get

gen_ai.prompt.name

The name of the prompt being retrieved

resources/read, resources/subscribe, resources/unsubscribe

mcp.resource.uri

The URI of the resource

Error Attributes

When a request fails, the span status is set to ERROR and additional attributes are recorded:

Attribute Description

error.type

tool_error for application-level tool errors, the error code for JSON-RPC errors, or the exception class name for unexpected exceptions

rpc.jsonrpc.error_code

The JSON-RPC error code (e.g., -32600 for invalid request)

rpc.jsonrpc.error_message

The JSON-RPC error message text

Context Propagation

MCP uses the _meta field in JSON-RPC params as the carrier for W3C Trace Context propagation. This is an MCP-specific mechanism, distinct from HTTP header propagation.

When a client includes traceparent and tracestate keys in the _meta field of a request, the server extracts this context and creates a child span. This allows distributed traces to flow from client to server regardless of the underlying transport.

For server-to-client callbacks (sampling, elicitation, roots listing), the server injects its current trace context into the _meta field of the outgoing request, allowing the client to continue the trace.

If a span is already present in the server side, independent of the MCP message OTel context, it will be mapped in the span with a link.

Metrics

The Quarkus MCP Server extension provides built-in metrics integration when the Quarkus Micrometer extension is present. The feature is disabled by default and must be explicitly enabled through configuration.

Metrics are collected for:

  • Active connection counts (gauge)

  • Request durations for all MCP protocol methods (timers)

  • Request success and failure rates (timers with failure tags)

All metrics can be exported to any Micrometer-supported monitoring system including Prometheus, Datadog, Graphite, InfluxDB, and others.

Prerequisites

The following dependency must be present to enable metrics:

<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-micrometer</artifactId>
</dependency>

In general, you also need a Micrometer Registry implementation, such as, for Prometheus:

<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-micrometer-registry-prometheus</artifactId>
</dependency>

See the Quarkus Micrometer guide for other registry implementations.

When using a registry, you don’t need to declare the dependency on quarkus-micrometer anymore. It will be pulled automatically by transitivity.

Configuration

Metrics collection is controlled by the following configuration property:

quarkus.mcp.server.metrics.enabled=true

For multiple servers, you must enable metrics for each server individually:

# Enable for default server
quarkus.mcp.server.metrics.enabled=true

# Enable for specific named servers
quarkus.mcp.server."main-server".metrics.enabled=true
quarkus.mcp.server."admin-server".metrics.enabled=true

Available Metrics

Connection Metrics

Active Connections Gauge

Tracks the current number of active MCP connections.

Metric Name

mcp.server.connections.active

Type

Gauge

Description

Number of currently active MCP connections

Tags

None

This metric helps you monitor:

  • Peak connection usage

  • Connection lifecycle patterns

  • Capacity planning needs

Request Metrics

All MCP protocol methods automatically get timer metrics that record request duration in milliseconds. The metric name follows the pattern mcp.server.requests.<method> where <method> is the JSON-RPC method name with slashes replaced by dots.

For example:

  • prompts/listmcp.server.requests.prompts.list

  • tools/callmcp.server.requests.tools.call

  • resources/readmcp.server.requests.resources.read

The most commonly used metrics are documented below.

Common Tags

All request timers include these tags:

Tag Description

mcp.server

The name of the MCP server instance (e.g., "default", or custom server names)

failure

Error type if the request failed, or "none" for successful requests. The value is the simple class name of the exception’s cause.

Tools Call Timer

Measures the duration of tool execution requests.

Metric Name

mcp.server.requests.tools.call

Type

Timer

Description

Duration of tool execution in milliseconds

Specific Tags

tool.name - the name of the tool being called

Tools List Timer

Measures the duration of listing available tools.

Metric Name

mcp.server.requests.tools.list

Type

Timer

Description

Duration of tool listing requests in milliseconds

Specific Tags

None

Resources Read Timer

Measures the duration of resource read requests.

Metric Name

mcp.server.requests.resources.read

Type

Timer

Description

Duration of resource read operations in milliseconds

Specific Tags

resource.uri - the URI of the resource being read

Resources List Timer

Measures the duration of listing available resources.

Metric Name

mcp.server.requests.resources.list

Type

Timer

Description

Duration of resource listing requests in milliseconds

Specific Tags

None

Resources Templates List Timer

Measures the duration of listing resource templates.

Metric Name

mcp.server.requests.resources.templates.list

Type

Timer

Description

Duration of resource template listing requests in milliseconds

Specific Tags

None

Prompts Get Timer

Measures the duration of prompt retrieval requests.

Metric Name

mcp.server.requests.prompts.get

Type

Timer

Description

Duration of prompt retrieval in milliseconds

Specific Tags

prompt.name - the name of the prompt being retrieved

Prompts List Timer

Measures the duration of listing available prompts.

Metric Name

mcp.server.requests.prompts.list

Type

Timer

Description

Duration of prompt listing requests in milliseconds

Specific Tags

None

Accessing Metrics

Prometheus Endpoint

With the Prometheus registry enabled, metrics are exposed at:

http://localhost:8080/q/metrics

Example Prometheus scrape configuration:

scrape_configs:
  - job_name: 'quarkus-mcp-server'
    metrics_path: '/q/metrics'
    static_configs:
      - targets: ['localhost:8080']

Programmatic Access

You can also access metrics programmatically by injecting the MeterRegistry:

import io.micrometer.core.instrument.MeterRegistry;
import jakarta.inject.Inject;

public class MetricsMonitor {

    @Inject
    MeterRegistry registry;

    public double getActiveConnections() {
        return registry.get("mcp.server.connections.active")
            .gauge()
            .value();
    }

    public double getToolCallCount(String toolName) {
        return registry.get("mcp.server.requests.tools.call")
            .tag("tool.name", toolName)
            .timer()
            .count();
    }
}

Configuration Reference

Property Description Default

quarkus.mcp.server.tracing.enabled

Enable tracing when OpenTelemetry is present

false

quarkus.mcp.server.metrics.enabled

Enable metrics collection when Micrometer is present

false

quarkus.mcp.server."server-name".metrics.enabled

Enable metrics for a specific server instance

Inherits from global setting