001/*
002 * Copyright 2022-2026 Revetware LLC.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package com.soklet;
018
019import org.jspecify.annotations.NonNull;
020
021import javax.annotation.concurrent.ThreadSafe;
022import java.net.InetSocketAddress;
023import java.util.Optional;
024
025/**
026 * An immutable point-in-time snapshot of MCP server diagnostics.
027 * <p>
028 * A retained snapshot never changes. Obtain a new snapshot to observe a later
029 * lifecycle state.
030 * <p>
031 * Lifecycle, handler-capacity, and stream values are captured together at one
032 * runtime linearization point. Protection and trace-correlation values are
033 * captured together at a separate security-control linearization point. No
034 * invariant spans those independently mutable domains.
035 *
036 * @author <a href="https://www.revetkn.com">Mark Allen</a>
037 */
038@ThreadSafe
039public interface McpServerDiagnostics {
040        /**
041         * The lifecycle status captured by this snapshot.
042         *
043         * @return the server status
044         */
045        @NonNull
046        McpServerStatus getStatus();
047
048        /**
049         * The effective bound address captured by this snapshot.
050         * <p>
051         * The address is empty until binding succeeds and includes the
052         * operating-system-assigned port when ephemeral port {@code 0} was
053         * configured. Once published, the effective address remains available as
054         * historical evidence in later shutdown and terminal snapshots.
055         *
056         * @return the effective or historically retained bound address, or empty when
057         * this server never bound
058         */
059        @NonNull
060        Optional<@NonNull InetSocketAddress> getBoundAddress();
061
062        /**
063         * The configured maximum number of application request handlers that may
064         * execute concurrently.
065         * <p>
066         * This value is stable across the owner lifecycle.
067         *
068         * @return the configured request-handler concurrency
069         */
070        @NonNull
071        Integer getRequestHandlerConcurrency();
072
073        /**
074         * The configured maximum number of admitted application requests that may
075         * wait for a request-handler execution slot.
076         * <p>
077         * This value is stable across the owner lifecycle.
078         *
079         * @return the configured request-handler queue capacity
080         */
081        @NonNull
082        Integer getRequestHandlerQueueCapacity();
083
084        /**
085         * The number of application request handlers occupying execution slots in
086         * this snapshot.
087         * <p>
088         * The value includes residual handlers that continue running after server
089         * stop and is between zero and {@link #getRequestHandlerConcurrency()}.
090         *
091         * @return the active handler-execution count
092         */
093        @NonNull
094        Integer getActiveHandlerExecutions();
095
096        /**
097         * The number of admitted application requests waiting for a request-handler
098         * execution slot in this snapshot.
099         * <p>
100         * The value is zero after a completed server stop transition and is between
101         * zero and {@link #getRequestHandlerQueueCapacity()}. A transient residual
102         * snapshot captured while failure cleanup is draining work may remain nonzero.
103         *
104         * @return the queued-request count
105         */
106        @NonNull
107        Integer getRequestHandlerQueueDepth();
108
109        /**
110         * The number of active SSE streams in this snapshot.
111         * <p>
112         * This count includes request-scoped streams, an MCP subscription once its
113         * acknowledgment stream has opened, and configured 2025 session GET bodies,
114         * including those awaiting physical cleanup. Opening a stream does not imply
115         * client receipt. The value is nonnegative and is zero when
116         * {@link #getStatus()} is {@link McpServerStatus#NOT_STARTED} or
117         * {@link McpServerStatus#TERMINATED}. Residual cleanup can keep this count
118         * nonzero after publication of the owner's immutable shutdown result.
119         *
120         * @return the active request-stream count
121         */
122        @NonNull
123        Integer getActiveRequestStreams();
124
125        /**
126         * The number of active subscription streams in this snapshot.
127         * <p>
128         * The count includes an MCP subscription once its acknowledgment stream has
129         * opened and configured 2025 session GET bodies, including those awaiting
130         * physical cleanup. Opening a stream does not imply client receipt. This
131         * value is nonnegative, never exceeds {@link #getActiveRequestStreams()},
132         * and is zero when {@link #getStatus()} is
133         * {@link McpServerStatus#NOT_STARTED} or {@link McpServerStatus#TERMINATED}.
134         * Residual cleanup can keep this count nonzero after publication of the
135         * owner's immutable shutdown result.
136         *
137         * @return the active subscription count
138         */
139        @NonNull
140        Integer getActiveSubscriptions();
141
142        /**
143         * The effective framework request-state protection mode in this snapshot.
144         * <p>
145         * This value is fixed when the server is built and remains stable across
146         * the one-shot owner lifecycle.
147         *
148         * @return the effective protection mode
149         */
150        @NonNull
151        McpProtectionMode getProtectionMode();
152
153        /**
154         * Whether an application-owned request-state protector is configured in this
155         * snapshot.
156         * <p>
157         * This value is {@code true} exactly when {@link #getProtectionMode()} is
158         * {@link McpProtectionMode#CUSTOM_PROTECTOR}. It reports provider selection
159         * without exposing the protector instance or its configuration. It does not
160         * report whether an operation declares
161         * {@link McpRequestStateMode#APPLICATION_PROTECTED}; it reports only custom-
162         * protector selection for canonical
163         * {@link McpRequestStateMode#FRAMEWORK_PROTECTED} state.
164         *
165         * @return whether a custom application request-state protector is configured
166         */
167        @NonNull
168        Boolean isApplicationRequestStateProtectorConfigured();
169
170        /**
171         * The secret-free fingerprint of the complete live production protection key
172         * ring in this snapshot.
173         * <p>
174         * The fingerprint is present exactly when {@link #getProtectionMode()} is
175         * {@link McpProtectionMode#PRODUCTION_KEYRING}. Successful live ring
176         * mutations are reflected only in subsequently obtained snapshots. The value
177         * excludes trace-correlation configuration, request-state epochs, and cursors,
178         * and exposes neither raw keys nor per-key fingerprint tags. It is operational
179         * deployment-comparison metadata, not an authentication input.
180         *
181         * @return the live production keyring fingerprint, or the empty optional
182         */
183        @NonNull
184        Optional<@NonNull McpProtectionKeyringFingerprint>
185                        getProtectionKeyringFingerprint();
186
187        /**
188         * The secret-free fingerprint of the active trace-correlation configuration
189         * in this snapshot.
190         * <p>
191         * The fingerprint is present exactly when trace correlation was enabled at
192         * server construction. Successful trace-key rotations are reflected only in
193         * subsequently obtained snapshots. This value is independent of the request-
194         * state protection mode, exposes no raw key material, and is operational
195         * deployment-comparison metadata rather than a token-derivation or
196         * authentication input.
197         *
198         * @return the active trace-correlation configuration fingerprint, or the empty
199         *         optional when trace correlation is disabled
200         */
201        @NonNull
202        Optional<@NonNull McpTraceCorrelationFingerprint>
203                        getTraceCorrelationFingerprint();
204}