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.time.Duration; 023import java.util.Optional; 024 025/** 026 * Thread-safe handle for one asynchronous off-network MCP request. 027 * 028 * @author <a href="https://www.revetkn.com">Mark Allen</a> 029 */ 030@ThreadSafe 031public interface McpSimulation extends AutoCloseable { 032 /** 033 * Waits up to {@code timeout} for the immutable response head. 034 * <p> 035 * A zero timeout performs a nonblocking check. Very large positive durations 036 * are saturated to the longest supported wait. Response reads are repeatable. 037 * 038 * @param timeout maximum time to wait; must not be negative 039 * @return the response when available, otherwise empty 040 * @throws InterruptedException if the waiting thread is interrupted 041 * @throws IllegalArgumentException if {@code timeout} is negative 042 * @throws NullPointerException if {@code timeout} is null 043 */ 044 @NonNull 045 Optional<@NonNull McpSimulationResponse> awaitResponse( 046 @NonNull Duration timeout) throws InterruptedException; 047 048 /** 049 * Waits up to {@code timeout} for and removes the next captured SSE item. 050 * Removing an item releases a pending-item slot but does not refund captured 051 * bytes. A zero timeout performs a nonblocking check, and very large positive 052 * durations are saturated to the longest supported wait. Unlike response and 053 * completion reads, successful item reads are destructive. 054 * 055 * @param timeout maximum time to wait; must not be negative 056 * @return the next item when available, otherwise empty 057 * @throws InterruptedException if the waiting thread is interrupted 058 * @throws IllegalArgumentException if {@code timeout} is negative 059 * @throws NullPointerException if {@code timeout} is null 060 */ 061 @NonNull 062 Optional<@NonNull McpSimulationStreamItem> awaitStreamItem( 063 @NonNull Duration timeout) throws InterruptedException; 064 065 /** 066 * Waits up to {@code timeout} for immutable terminal completion. 067 * <p> 068 * A zero timeout performs a nonblocking check. Very large positive durations 069 * are saturated to the longest supported wait. Completion reads are 070 * repeatable. 071 * 072 * @param timeout maximum time to wait; must not be negative 073 * @return completion when available, otherwise empty 074 * @throws InterruptedException if the waiting thread is interrupted 075 * @throws IllegalArgumentException if {@code timeout} is negative 076 * @throws NullPointerException if {@code timeout} is null 077 */ 078 @NonNull 079 Optional<@NonNull McpSimulationCompletion> awaitCompletion( 080 @NonNull Duration timeout) throws InterruptedException; 081 082 /** 083 * Performs a nonblocking terminal-state check. 084 * 085 * @return whether terminal completion is available 086 */ 087 @NonNull 088 Boolean isComplete(); 089 090 /** 091 * Simulates a client disconnect if the request remains active. Closing is 092 * idempotent, does not discard already captured values, and cannot replace an 093 * earlier terminal winner. 094 * <p> 095 * For MCP 2025-06-18 and 2025-11-25, disconnecting after progress has committed 096 * SSE detaches the response writer without canceling application work solely 097 * for that disconnect. Finite and uncommitted requests retain disconnect 098 * cancelation. Work retained after detachment remains subject to its request 099 * deadline and server shutdown; later progress and results are discarded. 100 */ 101 @Override 102 void close(); 103}