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.client.mcp.v20260728;
018
019import java.io.*;
020import java.util.*;
021
022import org.apache.juneau.bean.mcp.v20260728.*;
023
024/**
025 * Caller-supplied callback that answers one round of server→client MCP {@code 2026-07-28} SEP-2322
026 * elicitation requests during a client-side Multi-Round-Trip-Request (MRTR) auto-resume loop.
027 *
028 * <p>
029 * Passed to {@link McpClient#callToolWithElicitation}, {@link McpClient#getPromptWithElicitation}, and
030 * {@link McpClient#readResourceWithElicitation}: each time the server pauses a call with an {@code input_required}
031 * result, the client decodes that round's pending requests (there may be more than one) and invokes
032 * {@link #elicit(Map)} to obtain the matching answers, which it then echoes back on the resume call. This turns
033 * the otherwise hand-driven {@link McpClient#callRaw}/{@link ElicitationRequests}/{@link ElicitationResponses}
034 * loop into a single call plus one handler.
035 *
036 * <p>
037 * A handler answers by returning, keyed by the same server-assigned ids it was given, an {@link ElicitResult}
038 * per request it wishes to answer &mdash; an {@link ElicitAction#ACCEPT} with content, or an
039 * {@link ElicitAction#DECLINE}/{@link ElicitAction#CANCEL} to refuse. Decline/cancel answers are still sent back
040 * to the server (which decides the terminal outcome of a refused elicitation); the client does not short-circuit
041 * them locally.
042 *
043 * @since 10.0.0
044 */
045@FunctionalInterface
046public interface McpElicitationHandler {
047
048   /**
049    * Answers one round of elicitation requests.
050    *
051    * <p>
052    * The returned map may legitimately omit ids the handler chooses not to answer (the server may then
053    * re-pause, bounded by the auto-resume loop's max-rounds guard); returning <jk>null</jk> outright is illegal
054    * and causes the auto-resume loop to throw {@link IllegalArgumentException}; and any extra/unknown ids
055    * present in the returned map are echoed back to the server unvalidated.
056    *
057    * @param requests The pending requests for this round, keyed by server-assigned id (decoded via
058    *    {@link ElicitationRequests#requests(Map)}). Never <jk>null</jk>; may contain more than one entry, and an
059    *    individual value may be <jk>null</jk> if the corresponding raw entry was absent/<jk>null</jk>.
060    * @return The answers keyed by the same server-assigned ids. Must not be <jk>null</jk>. An
061    *    {@link ElicitResult} value must not be <jk>null</jk>. Use a {@link LinkedHashMap} for deterministic
062    *    ordering of the echoed {@code inputResponses}. May legitimately omit ids the handler chooses not to
063    *    answer (the server may then re-pause, bounded by the loop's max-rounds guard).
064    * @throws IOException If the handler performs its own I/O (e.g. prompting a remote user) and it fails; the
065    *    auto-resume loop propagates it to the caller unchanged.
066    */
067   Map<String,ElicitResult> elicit(Map<String,ElicitRequest> requests) throws IOException;
068}