This is an automated email from the ASF dual-hosted git repository.

jamesbognar pushed a commit to branch docs
in repository https://gitbox.apache.org/repos/asf/juneau.git


The following commit(s) were added to refs/heads/docs by this push:
     new f8a1283b51 docs: MCP v2 McpOptions config consolidation + Elicitation 
split (TODO-330)
f8a1283b51 is described below

commit f8a1283b513935e6cc4872859fd39834547e668e
Author: James Bognar <[email protected]>
AuthorDate: Tue Aug 4 18:27:40 2026 -0700

    docs: MCP v2 McpOptions config consolidation + Elicitation split (TODO-330)
    
    Update MCP setup/recipe/reference pages and 10.0.0 release notes for the new
    McpOptions aggregate config, per-binding stateful defaults, and the
    ElicitationRequests / ElicitationResponses client-side split.
    
    Co-authored-by: Cursor <[email protected]>
---
 pages/release-notes/10.0.0.md                | 17 ++++++-
 pages/topics/11.02.JuneauMcpChoosingSetup.md |  2 +-
 pages/topics/11.03.JuneauMcpRecipes.md       | 15 ++++--
 pages/topics/11.04.JuneauRestServerMcp.md    | 75 ++++++++++++++++++++--------
 pages/topics/11.05.JuneauRestClientMcp.md    | 19 ++++---
 5 files changed, 95 insertions(+), 33 deletions(-)

diff --git a/pages/release-notes/10.0.0.md b/pages/release-notes/10.0.0.md
index d590bb9e81..3d1780a7b5 100644
--- a/pages/release-notes/10.0.0.md
+++ b/pages/release-notes/10.0.0.md
@@ -899,7 +899,7 @@ The `2026-07-28` bean and REST-server adapter modules 
(`juneau-bean-mcp-v2026072
 
 - **Cache hints** — `tools/list`, `prompts/list`, `resources/list`, 
`resources/templates/list`, and `resources/read` results can each carry a 
nullable, top-level `ttlMs` (`Integer`) and `cacheScope` (`McpCacheScope`: 
`public`/`private`) pair, via the new `CacheableResult<T>` CRTP base that 
`ListToolsResult`, `ListPromptsResult`, `ListResourcesResult`, 
`ListResourceTemplatesResult`, and `ReadResourceResult` all extend. Fields are 
omitted from the wire when unset — there is no forced defau [...]
 - **`resources/templates/list`** — a new v2-only endpoint 
(`McpMethods.RESOURCES_TEMPLATES_LIST`) listing `ResourceTemplate` descriptors 
(`uriTemplate`, `name`, `title`, `description`, `mimeType`) registered via the 
neutral `McpServerConfig.addResourceTemplate(McpResourceTemplateSpec)`. 
Registering at least one resource template auto-derives the `resources` 
capability, same as resources. The pre-built neutral `McpResourceTemplateSpec` 
descriptor and this endpoint are designed for reuse b [...]
-- **Static, adapter-owned configuration only** — a server configures cache 
hints once, at construction time, via the new `McpCacheConfig`/`McpCacheHint` 
types (`createCacheConfig()` on `McpRestServlet`, `cacheConfig()` on 
`McpEndpoint`). Precedence is atomic per list method (method-specific hint, 
else a shared default, else no cache fields) and, for `resources/read`, adds an 
exact-URI override map ahead of a `resourcesRead` default. Juneau does **not** 
implement client-side caching, does [...]
+- **Static, adapter-owned configuration only** — a server configures cache 
hints once, at construction time, via the new `McpCacheConfig`/`McpCacheHint` 
types, mutated in place through the `cache(Consumer<McpCacheConfig>)` 
configure-block on the `McpOptions` aggregate (see the config-consolidation 
entry further down this page). Precedence is atomic per list method 
(method-specific hint, else a shared default, else no cache fields) and, for 
`resources/read`, adds an exact-URI override map [...]
 
 See 
[juneau-rest-server-mcp](/docs/topics/JuneauRestServerMcp#cache-hints-mcp-2026-07-28-sep-2549)
 and 
[juneau-bean-mcp-v20260728](/docs/topics/JuneauBeanMcp#mcp-2026-07-28-cache-hints-resource-templates)
 for the full topics.
 
@@ -928,6 +928,21 @@ See 
[juneau-rest-server-mcp](/docs/topics/JuneauRestServerMcp#resource-templates
 
 See 
[juneau-rest-server-mcp](/docs/topics/JuneauRestServerMcp#trace-context-propagation-mcp-2026-07-28)
 (Spring Boot + trace-context sections), 
[juneau-bean-mcp-v20260728](/docs/topics/JuneauBeanMcp#mcp-2026-07-28-metadata-and-trace-context-_meta)
 (bean catalog), and 
[Observability](/docs/topics/RestServerObservability#mcp-trace-context-propagation-2026-07-28)
 (framework-level seam + OTel bridge) for the full topics.
 
+### MCP `2026-07-28` — `McpOptions` config consolidation (TODO-330)
+
+`2026-07-28`-only. The six previously-separate per-binding behavior-config 
hooks the v2 adapter accumulated across the MRTR, cache-hints, and 
subscriptions work above (`capabilities`, `instructions`, `cache`, `mrtr`, 
`subscriptions`, `subscriptionBroker` — spread across mismatched `xxxConfig()` 
single-method and `createXxx()`/`getXxx()` pair idioms, with divergent defaults 
between the mixin and servlet paths) are consolidated into a single aggregate, 
**before this never-shipped API's fir [...]
+
+- **New `McpOptions`** (`org.apache.juneau.rest.server.mcp.v20260728`) — a 
mutable-setup fluent bean, same idiom as the neutral `McpServerConfig` and the 
nested `McpCacheConfig`/`McpMrtrConfig`/`McpSubscriptionsConfig` types it 
wraps. Plain `getXxx()`/`setXxx(...)` for 
`capabilities`/`instructions`/`subscriptionBroker`, plus `Consumer`-style 
configure-blocks (`cache(Consumer<McpCacheConfig>)`, 
`mrtr(Consumer<McpMrtrConfig>)`, 
`subscriptions(Consumer<McpSubscriptionsConfig>)`) that mutate [...]
+- **One override replaces six.** `McpRestServlet` gains `createMcpOptions()` 
(mirroring `createMcpConfig()`); `McpEndpoint` gains `getMcpOptions()` 
(mirroring `getMcpConfig()`). The prior six hooks (`capabilities()`, 
`instructions()`, `cacheConfig()`/`createCacheConfig()`, 
`mrtrConfig()`/`createMrtrConfig()`, 
`subscriptionsConfig()`/`createSubscriptionsConfig()`, the v2 
`subscriptionBroker()` override) and the wiring seam 
`subscriptionsConfigBean()` are gone from the user-visible surface.
+- **Uniform per-binding memoization.** `McpOptions` is invoked once per 
binding and published as a single internal `@Bean`, exactly like tools/prompts 
— and this internal publication is authoritative, taking precedence over any 
Spring `@Bean McpOptions` in the application context (Spring users inject their 
configuration *into* the `createMcpOptions()`/`getMcpOptions()` override 
instead of publishing a bare `@Bean McpOptions`). This also **unifies a prior 
default-sharing inconsistency**:  [...]
+- **Subscription broker folded in.** `McpOptions.getSubscriptionBroker()` 
defaults to `null` ("framework-derived"): the binding lazily derives and 
memoizes a `BasicMcpSubscriptionBroker` sized from `subscriptions`' 
`queueSize`. Call `setSubscriptionBroker(...)` to supply a custom broker 
instead.
+- **Client-side elicitation naming split, for symmetry.** 
`org.apache.juneau.rest.client.mcp.v20260728.ElicitationAccess` is replaced by 
an `ElicitationRequests` (reading server→client requests: 
`isInputRequired`/`requests`/`requestState`) + `ElicitationResponses` (encoding 
client→server answers: `toInputResponse`/`toInputResponses`) pair, matching the 
naming already used by the server-side helpers of the same names.
+- **Neutral core untouched.** `juneau-rest-server-mcp`'s revision-neutral 
`subscriptionBroker()`/`getSubscriptionBroker()` seam is unchanged; only the v2 
adapter delegates through `McpOptions`.
+
+Because `McpOptions` and the v2 adapter are never-shipped 10.0.0 APIs, this is 
a clean replace with no deprecation shims.
+
+See 
[juneau-rest-server-mcp](/docs/topics/JuneauRestServerMcp#configuring-the-endpoint-mcpoptions-mcp-2026-07-28)
 and 
[juneau-rest-client-mcp](/docs/topics/JuneauRestClientMcp#elicitation-mcp-2026-07-28-sep-2322)
 for the full topics.
+
 ### Bug Fixes
 
 - **Fixed RRPC method calls never dispatching over POST.** Every HTTP POST to 
an `@RestOp(method="RRPC")` operation previously returned a 404 instead of 
reaching the target method. `RrpcRestOpSession` derived the RRPC method key by 
splitting the request path on the last `/`, but RRPC keys are of the form 
`methodName/(paramTypes)` and themselves contain a `/`, so the method name was 
stripped off and the lookup always fell through to `NotFound`. The key is now 
derived from the already-comp [...]
diff --git a/pages/topics/11.02.JuneauMcpChoosingSetup.md 
b/pages/topics/11.02.JuneauMcpChoosingSetup.md
index 79e82caf27..41ea7989ec 100644
--- a/pages/topics/11.02.JuneauMcpChoosingSetup.md
+++ b/pages/topics/11.02.JuneauMcpChoosingSetup.md
@@ -28,7 +28,7 @@ If you don't have a specific reason to target `2025-06-18` 
(an existing client t
 
 ## 2. Dedicated servlet vs mixin
 
-Both paths bind the same revision and expose the same hooks (`capabilities()`, 
cache/MRTR/subscriptions config); they differ only in how the endpoint attaches 
to your REST resource.
+Both paths bind the same revision and expose the same config surface — 
`getMcpConfig()`/`createMcpConfig()` for tool/prompt/resource registration, 
plus (on `2026-07-28`) a single `getMcpOptions()`/`createMcpOptions()` override 
for behavior configuration 
(capabilities/instructions/cache/MRTR/subscriptions/broker, all on one 
`McpOptions` bean) — they differ only in how the endpoint attaches to your REST 
resource.
 
 **Dedicated servlet** — use when MCP is the *only* thing this resource does, 
or you're starting fresh:
 
diff --git a/pages/topics/11.03.JuneauMcpRecipes.md 
b/pages/topics/11.03.JuneauMcpRecipes.md
index 1ee82c7bc3..3151bf9255 100644
--- a/pages/topics/11.03.JuneauMcpRecipes.md
+++ b/pages/topics/11.03.JuneauMcpRecipes.md
@@ -226,7 +226,7 @@ McpToolHandler confirmDeleteTool = McpToolHandler.of(
 - The client answers, then re-sends the call; on that round, 
`McpMrtrResumeContext` is present, and `ElicitationResponses.get(ctx, id)` 
decodes the typed `ElicitResult` keyed by the same `id` you posed the question 
under.
 - `ElicitResult.getContent()` is populated only when `getAction() == 
ElicitAction.ACCEPT`; a `DECLINE`/`CANCEL` answer carries no content.
 
-This requires no special server config beyond a v2 servlet/mixin — MRTR 
support is on by default (see 
`AbstractMcpRestServlet.createMrtrConfig()`/`McpRestServlet.getMrtrConfig()` in 
the [server reference](/docs/topics/JuneauRestServerMcp) to customize the 
codec, TTL, or round cap).
+This requires no special server config beyond a v2 servlet/mixin — MRTR 
support is on by default (see `McpOptions.mrtr(Consumer<McpMrtrConfig>)` in the 
[server reference](/docs/topics/JuneauRestServerMcp) to customize the codec, 
TTL, or round cap).
 
 ## Subscriptions (v2 only)
 
@@ -252,12 +252,19 @@ McpToolHandler touchFileTool = McpToolHandler.of(
 
 `McpSubscriptions` also exposes `toolsListChanged()`, `promptsListChanged()`, 
and `resourcesListChanged()` for list-level notifications.
 
-Optionally tune the broker (queue size, heartbeat, idle timeout) by overriding 
a hook on your servlet/endpoint:
+Optionally tune the broker (queue size, heartbeat, idle timeout) via the 
`subscriptions(Consumer<McpSubscriptionsConfig>)` configure-block on your 
servlet/endpoint's `McpOptions`:
 
 ```java
+// servlet path
 @Override
-protected McpSubscriptionsConfig createSubscriptionsConfig() {
-    return new McpSubscriptionsConfig().setIdleTimeoutMs(5 * 60_000L);
+protected McpOptions createMcpOptions() {
+    return new McpOptions().subscriptions(s -> s.setIdleTimeoutMs(5 * 
60_000L));
+}
+
+// mixin path
+@Override
+public McpOptions getMcpOptions() {
+    return new McpOptions().subscriptions(s -> s.setIdleTimeoutMs(5 * 
60_000L));
 }
 ```
 
diff --git a/pages/topics/11.04.JuneauRestServerMcp.md 
b/pages/topics/11.04.JuneauRestServerMcp.md
index 4ab2d2e024..11102bba9c 100644
--- a/pages/topics/11.04.JuneauRestServerMcp.md
+++ b/pages/topics/11.04.JuneauRestServerMcp.md
@@ -502,10 +502,45 @@ A prompt argument's `completer` is server behavior only — 
it's never mapped on
 
 ### Completions capability
 
-Both dated `ServerCapabilities` gain a nullable `completions` property, 
auto-derived alongside `tools`/`prompts`/`resources`: it's advertised (as an 
empty `{}` `CompletionCapability` marker) only when at least one 
prompt-argument completer or resource-template variable completer is currently 
registered — registering a template or prompt with no completer does not turn 
it on. As with the other auto-derived capability flags, an explicit 
`ServerCapabilities` override on the servlet/mixin `c [...]
+Both dated `ServerCapabilities` gain a nullable `completions` property, 
auto-derived alongside `tools`/`prompts`/`resources`: it's advertised (as an 
empty `{}` `CompletionCapability` marker) only when at least one 
prompt-argument completer or resource-template variable completer is currently 
registered — registering a template or prompt with no completer does not turn 
it on. As with the other auto-derived capability flags, an explicit 
`ServerCapabilities` override remains authoritative a [...]
 
 See 
[juneau-bean-mcp-v20250618](/docs/topics/JuneauBeanMcp#completions-completioncomplete-new-in-1000)
 for the `2025-06-18` completion wire-bean catalog (`CompleteRequest`, 
`CompletionReference`/`PromptReference`/`ResourceTemplateReference`, 
`CompletionArgument`, `CompletionContext`, `CompleteResult`, `Completion`, 
`CompletionCapability`) and the equivalent `2026-07-28` family.
 
+## Configuring the endpoint: `McpOptions` (MCP `2026-07-28`)
+
+**v2-only.** `McpOptions` (`org.apache.juneau.rest.server.mcp.v20260728`) is 
the single behavior-configuration aggregate for a `2026-07-28` binding — 
"*how*" the endpoint behaves, alongside the neutral `McpServerConfig`'s 
"*what*" it exposes (tools/prompts/resources). It consolidates six 
previously-separate hooks (`capabilities`, `instructions`, `cache`, `mrtr`, 
`subscriptions`, `subscriptionBroker`) into one mutable-setup fluent bean, 
supplied by a single override on each path:
+
+```java
+// Servlet-subclass path
+@Rest(path="/mcp")
+public class MyMcpServlet extends McpRestServlet {
+    @Override protected McpServerConfig createMcpConfig() {
+        return new McpServerConfig().setName("my-server").addTool(new 
MyEchoTool());
+    }
+    @Override protected McpOptions createMcpOptions() {           // optional
+        return new McpOptions()
+            .setInstructions("Use tool 'echo' to test.")
+            .cache(c -> c.setToolsList(new McpCacheHint().setTtlMs(60_000)))
+            .subscriptions(s -> s.setQueueSize(2048));
+    }
+}
+
+// Mixin path (incl. Spring via SpringMcpRestServlet)
+@Rest(path="/api")
+public class MyResource extends BasicRestServlet implements McpEndpoint {
+    @Override public McpServerConfig getMcpConfig() { return new 
McpServerConfig().addTool(new MyEchoTool()); }
+    @Override public McpOptions getMcpOptions()     { return new 
McpOptions().mrtr(m -> m.setTtlMs(600_000)); }
+}
+```
+
+Both `getCapabilities()`/`getInstructions()` are plain 
`getXxx()`/`setXxx(...)` properties. The three nested configs (`cache` → 
`McpCacheConfig`, `mrtr` → `McpMrtrConfig`, `subscriptions` → 
`McpSubscriptionsConfig`) are framework-owned instances: use the 
`cache(Consumer<McpCacheConfig>)`/`mrtr(Consumer<McpMrtrConfig>)`/`subscriptions(Consumer<McpSubscriptionsConfig>)`
 configure-blocks to mutate them in place rather than constructing (and needing 
to remember to keep stable) a replacement  [...]
+
+`McpOptions` is memoized exactly once per binding — the framework invokes 
`createMcpOptions()`/`getMcpOptions()` once and publishes the single result as 
an internal `@Bean`. This memoization matters because two of the six concepts 
are stateful: `mrtr` holds a random AES key (a sealed `requestState` can't be 
unsealed under a different key) and the subscription broker holds the live 
per-connection registry (a fresh one would silently split publishers from 
subscribers). Every binding gets i [...]
+
+This internal `@Bean` publication is **authoritative** and takes precedence 
over any Spring `@Bean McpOptions` in the application context — publishing a 
bare `@Bean McpOptions` in a Spring context does **not** get picked up in place 
of it. Spring users who want their configuration honored must inject their bean 
*into* the `createMcpOptions()`/`getMcpOptions()` override instead (for 
example, an `@Autowired` field read from there), as shown above.
+
+`getSubscriptionBroker()` defaults to `null`, meaning "framework-derived": the 
binding lazily derives a `BasicMcpSubscriptionBroker` sized from 
`subscriptions`' `queueSize` the first time one is needed, and memoizes that 
single derived instance for the binding's lifetime. Call 
`setSubscriptionBroker(...)` to supply a custom broker instead (for example, 
one deliberately shared across multiple bindings).
+
 ## Cache Hints (MCP `2026-07-28`, SEP-2549)
 
 The `2026-07-28` adapter (`org.apache.juneau.rest.server.mcp.v20260728`) adds 
two capabilities on top of the neutral core: SEP-2549 cache hints on five 
list/read results, and a `resources/templates/list` endpoint. Both are 
configured statically, at server-construction time — there is no 
dynamic/per-request cache callback, and neither concept exists on the neutral 
`juneau-rest-server-mcp` core or the `2025-06-18` adapter.
@@ -516,36 +551,34 @@ Resource templates are registered on the same neutral 
`McpServerConfig` used for
 
 ### Configuring cache hints
 
-`McpCacheConfig` (adapter-owned, immutable after construction) carries one 
`McpCacheHint` (nullable `ttlMs` + `McpCacheScope`) per list method, plus a 
`resourcesRead` default and an exact-URI override map for individual resource 
reads:
+`McpCacheConfig` carries one `McpCacheHint` (nullable `ttlMs` + 
`McpCacheScope`) per list method, plus a `resourcesRead` default and an 
exact-URI override map for individual resource reads. It's one of the nested 
configs on `McpOptions` — mutate it in place via the 
`cache(Consumer<McpCacheConfig>)` configure-block on the servlet's 
`createMcpOptions()` (or the mixin's `getMcpOptions()`):
 
 ```java
-private final McpCacheConfig cache = new McpCacheConfig()
-       .setDefaultHint(new McpCacheHint().setTtlMs(60_000))
-       .setToolsList(new McpCacheHint().setTtlMs(0))
-       .setResourcesRead(new 
McpCacheHint().setCacheScope(McpCacheScope.PUBLIC))
-       .addResourceReadOverride("file:///private",
-               new 
McpCacheHint().setTtlMs(5_000).setCacheScope(McpCacheScope.PRIVATE));
-
 @Override protected McpServerConfig createMcpConfig() {
        return new McpServerConfig().addResourceTemplate(new 
McpResourceTemplateSpec()
                
.setUriTemplate("file:///{name}").setName("files").setMimeType("text/plain"));
 }
 
-@Override protected McpCacheConfig createCacheConfig() {
-       return cache;
+@Override protected McpOptions createMcpOptions() {
+       return new McpOptions().cache(c -> c
+               .setDefaultHint(new McpCacheHint().setTtlMs(60_000))
+               .setToolsList(new McpCacheHint().setTtlMs(0))
+               .setResourcesRead(new 
McpCacheHint().setCacheScope(McpCacheScope.PUBLIC))
+               .addResourceReadOverride("file:///private",
+                       new 
McpCacheHint().setTtlMs(5_000).setCacheScope(McpCacheScope.PRIVATE)));
 }
 ```
 
-The `McpEndpoint` mixin path is the same shape, with a stable `cacheConfig()` 
override instead of `createCacheConfig()`:
+The `McpEndpoint` mixin path reads the same shape from `getMcpOptions()`:
 
 ```java
-private final McpCacheConfig cache = new McpCacheConfig().setToolsList(new 
McpCacheHint().setTtlMs(0));
-
-@Override public McpCacheConfig cacheConfig() {
-       return cache;
+@Override public McpOptions getMcpOptions() {
+       return new McpOptions().cache(c -> c.setToolsList(new 
McpCacheHint().setTtlMs(0)));
 }
 ```
 
+`McpOptions` is memoized once per binding (see [Configuring the endpoint: 
`McpOptions`](#configuring-the-endpoint-mcpoptions-mcp-2026-07-28) above), so 
`cache` behaves as effectively-immutable after construction, exactly as before.
+
 **Precedence is atomic — a matched hint's `ttlMs`/`cacheScope` pair is applied 
as a whole, never merged field-by-field with a lower-precedence hint:**
 
 - **List methods** (`tools/list`, `prompts/list`, `resources/list`, 
`resources/templates/list`): the method-specific hint (e.g. `toolsList`) if 
set, else `defaultHint` if set, else no cache fields are written at all. An 
explicitly-set *empty* hint (both fields `null`) at a higher precedence still 
suppresses the lower one — it does not fall through.
@@ -665,19 +698,19 @@ Only the sealed `continuation` is tamper-evident across 
rounds; the per-round `a
 
 ### Configuring MRTR: `McpMrtrConfig`
 
-`McpMrtrConfig` is the adapter-owned configuration bean, placed exactly like 
`McpCacheConfig` (v2-adapter-only, never on the neutral core). It carries the 
`RequestStateCodec`, a `requestState` TTL (default 5 minutes), and a max-rounds 
cap (default 10). Supply it via the servlet's `createMrtrConfig()` hook (or the 
mixin's `mrtrConfig()`):
+`McpMrtrConfig` is the adapter-owned configuration bean, placed exactly like 
`McpCacheConfig` (v2-adapter-only, never on the neutral core). It carries the 
`RequestStateCodec`, a `requestState` TTL (default 5 minutes), and a max-rounds 
cap (default 10). It's one of the nested configs on 
[`McpOptions`](#configuring-the-endpoint-mcpoptions-mcp-2026-07-28) — mutate it 
in place via the `mrtr(Consumer<McpMrtrConfig>)` configure-block:
 
 ```java
 @Override
-protected McpMrtrConfig createMrtrConfig() {
-    return new McpMrtrConfig()
+protected McpOptions createMcpOptions() {
+    return new McpOptions().mrtr(m -> m
         .setCodec(new AeadRequestStateCodec())   // or a shared/rotating-key 
implementation
         .setTtlMs(5 * 60 * 1000L)
-        .setMaxRounds(10);
+        .setMaxRounds(10));
 }
 ```
 
-The config is memoized at binding time and treated as read-only afterward 
(each `AeadRequestStateCodec` holds a distinct random key, so exactly one 
instance must be published per binding).
+`McpOptions` (and hence `mrtr`) is memoized once per binding and treated as 
read-only afterward (each `AeadRequestStateCodec` holds a distinct random key, 
so exactly one instance must be published per binding — the mixin path gets its 
own per-binding key too, with no sharing across separate endpoint instances).
 
 ### Error codes
 
diff --git a/pages/topics/11.05.JuneauRestClientMcp.md 
b/pages/topics/11.05.JuneauRestClientMcp.md
index 5f7cb606b7..eb0ac42497 100644
--- a/pages/topics/11.05.JuneauRestClientMcp.md
+++ b/pages/topics/11.05.JuneauRestClientMcp.md
@@ -31,24 +31,31 @@ The illustrative server-initiated method name used 
elsewhere in this codebase's
 
 ## Elicitation (MCP `2026-07-28`, SEP-2322)
 
-**v2-only.** `org.apache.juneau.rest.client.mcp.v20260728.ElicitationAccess` 
is a static helper for driving elicitation over `McpClient.callRaw(...)`'s raw 
`Map<String,Object>` result — the typed `callTool`/`getPrompt`/`readResource` 
methods cannot represent a paused `input_required` result or set 
`requestState`/`inputResponses` on a resume call, so a caller must go through 
`callRaw(...)` for the resumable leg of the loop.
+**v2-only.** Two static helper classes in 
`org.apache.juneau.rest.client.mcp.v20260728` drive elicitation over 
`McpClient.callRaw(...)`'s raw `Map<String,Object>` result — the typed 
`callTool`/`getPrompt`/`readResource` methods cannot represent a paused 
`input_required` result or set `requestState`/`inputResponses` on a resume 
call, so a caller must go through `callRaw(...)` for the resumable leg of the 
loop:
+
+| Helper | Purpose |
+|---|---|
+| `ElicitationRequests` | Reads the server's `input_required` pause out of a 
raw result: `isInputRequired`, `requests` (`Map<String, ElicitRequest>`), 
`requestState`. |
+| `ElicitationResponses` | Encodes the client's answers back into a resume 
call: `toInputResponse`/`toInputResponses`. |
+
+This mirrors the server-side `ElicitationRequests`/`ElicitationResponses` pair 
(see 
[juneau-rest-server-mcp](/docs/topics/JuneauRestServerMcp#elicitation-mcp-2026-07-28-sep-2322))
 — same class names, same direction-pair scheme, disambiguated by package: the 
client *reads* requests / *writes* responses, the server *writes* requests / 
*reads* responses.
 
 ```java
 import org.apache.juneau.bean.mcp.v20260728.*;
 import org.apache.juneau.rest.client.mcp.v20260728.*;
 
 var paused = client.callRaw(McpMethods.TOOLS_CALL, new 
CallToolRequest().setName("confirm").setArguments(Map.of()));
-if (ElicitationAccess.isInputRequired(paused)) {
-    var questions = ElicitationAccess.requests(paused);   // Map<String, 
ElicitRequest>
+if (ElicitationRequests.isInputRequired(paused)) {
+    var questions = ElicitationRequests.requests(paused);   // Map<String, 
ElicitRequest>
     // ... show questions.get("confirm").getMessage() to the end user, collect 
an answer ...
     var answer = new 
ElicitResult().setAction(ElicitAction.ACCEPT).putContent("confirm", true);
     var completed = client.callRaw(McpMethods.TOOLS_CALL, new 
CallToolRequest().setName("confirm")
-        .setRequestState(ElicitationAccess.requestState(paused))
-        .setInputResponses(ElicitationAccess.toInputResponse("confirm", 
answer)));
+        .setRequestState(ElicitationRequests.requestState(paused))
+        .setInputResponses(ElicitationResponses.toInputResponse("confirm", 
answer)));
 }
 ```
 
-`ElicitationAccess` works at the raw map/JSON level rather than exposing typed 
overloads per concrete request bean, because 
`CallToolRequest`/`GetPromptRequest`/`ReadResourceRequest` share no common 
"has-`inputResponses`-and-`requestState`" interface — a caller resuming a 
specific one of the three makes its own final 
`.setInputResponses(...).setRequestState(...)` call on the concrete bean it 
already knows it holds. 
`ElicitationAccess.toInputResponses(Map<String,ElicitResult>)` encodes se [...]
+Both helpers work at the raw map/JSON level rather than exposing typed 
overloads per concrete request bean, because 
`CallToolRequest`/`GetPromptRequest`/`ReadResourceRequest` share no common 
"has-`inputResponses`-and-`requestState`" interface — a caller resuming a 
specific one of the three makes its own final 
`.setInputResponses(...).setRequestState(...)` call on the concrete bean it 
already knows it holds. 
`ElicitationResponses.toInputResponses(Map<String,ElicitResult>)` encodes 
several [...]
 
 See 
[juneau-rest-server-mcp](/docs/topics/JuneauRestServerMcp#elicitation-mcp-2026-07-28-sep-2322)
 for the server-side helper half of this loop.
 

Reply via email to