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}