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 * https://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 java.util.Collections;
022import java.util.EnumSet;
023import java.util.LinkedHashSet;
024import java.util.Optional;
025import java.util.Set;
026
027import static java.util.Objects.requireNonNull;
028
029/**
030 * An exact MCP core protocol revision.
031 *
032 * <p>
033 * This type may gain reviewed constants in Soklet 4.x; use a forward-compatible default when switching over its values.
034 *
035 * @author <a href="https://www.revetkn.com">Mark Allen</a>
036 */
037public enum McpProtocolVersion {
038        /** MCP 2025-03-26. */
039        V2025_03_26("2025-03-26"),
040        /** MCP 2025-06-18. */
041        V2025_06_18("2025-06-18"),
042        /** MCP 2025-11-25. */
043        V2025_11_25("2025-11-25"),
044        /** MCP 2026-07-28. */
045        V2026_07_28("2026-07-28");
046
047        @NonNull
048        private final String wireValue;
049
050        McpProtocolVersion(@NonNull String wireValue) {
051                this.wireValue = wireValue;
052        }
053
054        /** @return the exact MCP protocol revision sent on the wire */
055        @NonNull
056        public String getWireValue() {
057                return this.wireValue;
058        }
059
060        /**
061         * Finds a known exact revision without selecting a fallback.
062         *
063         * @param wireValue wire revision
064         * @return the corresponding revision, or empty for an unknown value
065         */
066        @NonNull
067        public static Optional<@NonNull McpProtocolVersion> fromWireValue(
068                        @NonNull String wireValue) {
069                requireNonNull(wireValue);
070                for (McpProtocolVersion version : values()) {
071                        if (version.wireValue.equals(wireValue))
072                                return Optional.of(version);
073                }
074                return Optional.empty();
075        }
076
077        @NonNull
078        static Set<@NonNull McpProtocolVersion> requiredSet(
079                        @NonNull Set<@NonNull McpProtocolVersion> protocolVersions) {
080                Set<McpProtocolVersion> copy = optionalSet(protocolVersions);
081                if (copy.isEmpty())
082                        throw new IllegalArgumentException(
083                                        "At least one MCP protocol version is required.");
084                return copy;
085        }
086
087        @NonNull
088        static Set<@NonNull McpProtocolVersion> optionalSet(
089                        @NonNull Set<@NonNull McpProtocolVersion> protocolVersions) {
090                requireNonNull(protocolVersions);
091                EnumSet<McpProtocolVersion> selected = EnumSet.noneOf(McpProtocolVersion.class);
092                for (McpProtocolVersion version : protocolVersions)
093                        selected.add(requireNonNull(version));
094                return Collections.unmodifiableSet(new LinkedHashSet<>(selected));
095        }
096}