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.util.Optional;
023import java.util.Set;
024
025import static java.util.Objects.requireNonNull;
026
027/**
028 * Contract for discovering MCP endpoints and composing programmatic handlers onto them.
029 * <p>
030 * Standard threadsafe implementations can be acquired via:
031 * <ul>
032 *   <li>{@link #fromClasspathIntrospection()} for production discovery via {@link SokletProcessor}-generated metadata</li>
033 *   <li>{@link #fromClasses(Set)} for runtime reflection against a known set of endpoint classes</li>
034 * </ul>
035 * <p>
036 * Programmatic handlers may be layered onto either base resolver via the {@code withX(...)} methods.
037 *
038 * @author <a href="https://www.revetkn.com">Mark Allen</a>
039 */
040@ThreadSafe
041public interface McpHandlerResolver {
042        /**
043         * Resolves MCP endpoint metadata for the given endpoint class.
044         *
045         * @param endpointClass the endpoint class
046         * @return resolved endpoint registration metadata, if available
047         */
048        @NonNull
049        Optional<McpEndpointRegistration> endpointRegistrationForClass(@NonNull Class<? extends McpEndpoint> endpointClass);
050
051        /**
052         * Vends the set of all registered MCP endpoint metadata in the system.
053         *
054         * @return all resolved endpoint registrations
055         */
056        @NonNull
057        Set<@NonNull McpEndpointRegistration> getEndpointRegistrations();
058
059        /**
060         * Returns a new resolver with the given tool handler layered onto the specified endpoint class.
061         *
062         * @param toolHandler   the tool handler to add
063         * @param endpointClass the endpoint class to which the handler belongs
064         * @return a new resolver instance containing the overlay
065         */
066        @NonNull
067        McpHandlerResolver withTool(@NonNull McpToolHandler toolHandler,
068                                                                                                                        @NonNull Class<? extends McpEndpoint> endpointClass);
069
070        /**
071         * Returns a new resolver with the given prompt handler layered onto the specified endpoint class.
072         *
073         * @param promptHandler the prompt handler to add
074         * @param endpointClass the endpoint class to which the handler belongs
075         * @return a new resolver instance containing the overlay
076         */
077        @NonNull
078        McpHandlerResolver withPrompt(@NonNull McpPromptHandler promptHandler,
079                                                                                                                                @NonNull Class<? extends McpEndpoint> endpointClass);
080
081        /**
082         * Returns a new resolver with the given resource handler layered onto the specified endpoint class.
083         *
084         * @param resourceHandler the resource handler to add
085         * @param endpointClass   the endpoint class to which the handler belongs
086         * @return a new resolver instance containing the overlay
087         */
088        @NonNull
089        McpHandlerResolver withResource(@NonNull McpResourceHandler resourceHandler,
090                                                                                                                                        @NonNull Class<? extends McpEndpoint> endpointClass);
091
092        /**
093         * Returns a new resolver with the given resource-list handler layered onto the specified endpoint class.
094         *
095         * @param resourceListHandler the resource-list handler to add
096         * @param endpointClass       the endpoint class to which the handler belongs
097         * @return a new resolver instance containing the overlay
098         */
099        @NonNull
100        McpHandlerResolver withResourceList(@NonNull McpResourceListHandler resourceListHandler,
101                                                                                                                                                        @NonNull Class<? extends McpEndpoint> endpointClass);
102
103        /**
104         * Acquires a threadsafe {@link McpHandlerResolver} implementation which discovers MCP endpoints by examining a processor-generated lookup table.
105         * <p>
106         * This implementation requires that your application be compiled with the {@link SokletProcessor} annotation processor.
107         * The returned instance is guaranteed to be a JVM-wide singleton.
108         *
109         * @return a resolver backed by classpath introspection
110         */
111        @NonNull
112        static McpHandlerResolver fromClasspathIntrospection() {
113                return DefaultMcpHandlerResolver.fromClasspathIntrospection();
114        }
115
116        /**
117         * Acquires a threadsafe {@link McpHandlerResolver} implementation which discovers MCP endpoints by reflecting over the given endpoint classes.
118         * <p>
119         * This method is guaranteed to return a new instance.
120         *
121         * @param endpointClasses the endpoint classes to inspect
122         * @return a resolver backed by the provided endpoint classes
123         */
124        @NonNull
125        static McpHandlerResolver fromClasses(@NonNull Set<@NonNull Class<?>> endpointClasses) {
126                requireNonNull(endpointClasses);
127                return DefaultMcpHandlerResolver.fromClasses(endpointClasses);
128        }
129}