001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.rest.server.mcp; 018 019 020import java.util.*; 021import java.util.function.*; 022 023import org.apache.juneau.commons.inject.*; 024import static org.apache.juneau.commons.utils.Shorts.*; 025 026/** 027 * Handler for a single MCP prompt. 028 * 029 * <p> 030 * Implementations declare a {@link #descriptor() descriptor} (the {@link McpPromptSpec} returned by 031 * {@code prompts/list}) and a {@link #get(Map, BeanStore) get} body invoked when the matching 032 * {@code prompts/get} method runs. 033 * 034 * <p> 035 * This is a genuine two-method contract, not a single-method one: both {@link #descriptor()} and 036 * {@link #get(Map, BeanStore)} are abstract, so it is deliberately <b>not</b> annotated 037 * {@code @FunctionalInterface} and a bare lambda cannot implement it. Routing calls {@link #descriptor()} 038 * on every registered handler for both {@code prompts/list} and {@code prompts/get}, so a handler with no 039 * usable descriptor is not a valid handler; making {@link #descriptor()} abstract catches that at compile 040 * time instead of the first request to reach it at runtime. Use {@link #of(McpPromptSpec, BiFunction)} for 041 * the common case of wiring both in a single expression. 042 */ 043public interface McpPromptHandler { 044 045 /** 046 * Builds a handler from a fixed descriptor and a {@code get} lambda. 047 * 048 * <p> 049 * The sanctioned one-expression path for registering a prompt: unlike a bare lambda (which cannot 050 * satisfy this two-method interface at all), this factory wires both {@link #descriptor()} and 051 * {@link #get(Map, BeanStore)} from a single call. 052 * 053 * @param descriptor The static descriptor returned from every {@link #descriptor()} call. Must not be 054 * <jk>null</jk> and must carry a non-blank {@link McpPromptSpec#getName() name} (routing matches 055 * incoming {@code prompts/get} requests on name, so a nameless prompt would be silently unreachable). 056 * @param get The get body, invoked with the incoming arguments and the per-request bean store. Must not be <jk>null</jk>. 057 * @return A new handler wiring both. Never <jk>null</jk>. 058 */ 059 static McpPromptHandler of(McpPromptSpec descriptor, BiFunction<Map<String,Object>,BeanStore,McpPromptOutcome> get) { 060 reqnn("descriptor", descriptor); 061 reqnb("descriptor.getName()", descriptor.getName()); 062 reqnn("get", get); 063 return new McpPromptHandler() { 064 @Override public McpPromptSpec descriptor() { 065 return descriptor; 066 } 067 068 @Override public McpPromptOutcome get(Map<String,Object> arguments, BeanStore ctx) { 069 return get.apply(arguments, ctx); 070 } 071 }; 072 } 073 074 /** 075 * Returns the static descriptor for this prompt. 076 * 077 * <p> 078 * The {@link McpPromptSpec#getName() name} value is used by the bound {@link McpRevision} to route 079 * incoming {@code prompts/get} requests, so each handler in an {@link McpServerConfig} must use a 080 * unique name. 081 * 082 * @return The prompt descriptor. Never {@code null}. 083 */ 084 McpPromptSpec descriptor(); 085 086 /** 087 * Renders the prompt. 088 * 089 * @param arguments The arguments object passed in the JSON-RPC params (never {@code null}; empty map when omitted). 090 * @param ctx Per-request bean store. Never {@code null}. 091 * @return The rendered prompt. Never {@code null}. 092 */ 093 McpPromptOutcome get(Map<String,Object> arguments, BeanStore ctx); 094}