Class McpClient
- All Implemented Interfaces:
Closeable,AutoCloseable
Extends AbstractMcpClient, adding one typed method per McpMethods). Every method stamps the SEP-2243 params._meta envelope (protocol
version, client capabilities, client info, and any supplied trace-context fields), builds the
corresponding v2 request bean, wraps it in a JsonRpcRequest with the required
Mcp-Method/Mcp-Name headers, delegates to the inherited AbstractMcpClient.send(JsonRpcRequest, Map),
and then either returns the result re-marshaled into its typed v2 result bean, or throws an
McpException built from the response's error.
An optional McpResponseCache can be supplied via McpClient.Builder.responseCache(McpResponseCache)
to serve repeat identical calls from cache instead of the wire, keyed off the method and business params
(never the per-call _meta, so a per-request trace-context supplier does not defeat the cache).
A server-initiated request delivered over the duplex event-stream channel is routed through the
McpDuplexDispatcher registered via setServerRequestHandler(McpServerRequestHandler).
- Since:
- 10.0.0
-
Nested Class Summary
Nested Classes -
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final intDefault maximum number ofinput_requiredresume rounds the*WithElicitationhelpers will drive before throwingMcpElicitationLimitException. -
Method Summary
Modifier and TypeMethodDescriptionstatic McpClient.Builderbuilder()Creates a new builder.callRaw(String method, RequestParams<?> params) Performs a JSON-RPC call using a caller-supplied, fully-populated request bean, returning the raw result payload without deserializing into a specificResultsubtype.Sends "tools/call".callToolText(String name, Map<String, Object> arguments) Convenience forcallTool(java.lang.String, java.util.Map<java.lang.String, java.lang.Object>)followed byCallToolResult.firstText().callToolWithElicitation(String name, Map<String, Object> arguments, McpElicitationHandler handler) Invokes "tools/call", transparently answering any MCP2026-07-28SEP-2322input_requiredelicitation pauses viahandleruntil a terminal result is reached, using thedefaultmax-rounds bound.callToolWithElicitation(String name, Map<String, Object> arguments, McpElicitationHandler handler, int maxRounds) Invokes "tools/call", transparently answering anyinput_requiredelicitation pauses viahandleruntil a terminal result is reached, bounded bymaxRounds.complete(CompletionReference ref, String argumentName, String argumentValue, Map<String, String> contextArguments) Sends "completion/complete".static McpClientBuilds a client forendpointwith default settings and performs its one mandatory handshake call, returning a ready-to-use client.static McpClientconnect(McpClient.Builder builder) Builds a client from a caller-configured builder and performs its one mandatory handshake call, returning a ready-to-use client.Returns theServerDiscoverResultcached from the most recentserverDiscover()call.Sends "prompts/get".getPromptWithElicitation(String name, Map<String, Object> arguments, McpElicitationHandler handler) Invokes "prompts/get", transparently answering anyinput_requiredelicitation pauses viahandleruntil a terminal result is reached, using thedefaultmax-rounds bound.getPromptWithElicitation(String name, Map<String, Object> arguments, McpElicitationHandler handler, int maxRounds) Invokes "prompts/get", transparently answering anyinput_requiredelicitation pauses viahandleruntil a terminal result is reached, bounded bymaxRounds.listen(SubscriptionFilter filter, McpSubscriptionListener listener) Sends "subscriptions/listen", opening a managed, held-open notification stream on a background thread and dispatching decoded frames tolisteneruntil the returned handle is closed, the server completes gracefully, or the connection drops.Sends "prompts/list".Sends "resources/list".Sends "resources/templates/list".Sends "tools/list".ping()Sends "ping" to verify server liveness.readResource(String uri) Sends "resources/read".readResourceWithElicitation(String uri, McpElicitationHandler handler) Invokes "resources/read", transparently answering anyinput_requiredelicitation pauses viahandleruntil a terminal result is reached, using thedefaultmax-rounds bound.readResourceWithElicitation(String uri, McpElicitationHandler handler, int maxRounds) Invokes "resources/read", transparently answering anyinput_requiredelicitation pauses viahandleruntil a terminal result is reached, bounded bymaxRounds.Sends "server/discover".Registers the handler invoked for server-initiated requests delivered over the duplex event-stream channel (seeMcpDuplexDispatcher).Methods inherited from class org.apache.juneau.rest.client.mcp.AbstractMcpClient
close, openEventStream, openEventStream, openEventStream, send, send
-
Field Details
-
DEFAULT_MAX_ELICITATION_ROUNDS
Default maximum number ofinput_requiredresume rounds the*WithElicitationhelpers will drive before throwingMcpElicitationLimitException.- See Also:
-
-
Method Details
-
builder
Creates a new builder.- Returns:
- A new builder. Never
null .
-
connect
Builds a client forendpointwith default settings and performs its one mandatory handshake call, returning a ready-to-use client.2026-07-28has noinitializemethod -serverDiscover()is this revision's handshake - so unlikev20250618'sMcpClient, forgetting it is a real footgun: nothing in this class's type system forces a caller to call it beforecallTool(java.lang.String, java.util.Map<java.lang.String, java.lang.Object>),listTools(), etc. This is the sanctioned one-expression path for the common case of connecting with default settings; useconnect(Builder)to customize the transport, interceptors, or other builder settings first.- Parameters:
endpoint- The absolute endpoint URL (e.g."http://localhost:8080/mcp"). Must not benull .- Returns:
- A new client that has already completed
serverDiscover()exactly once. Nevernull . - Throws:
IOException- If a transport-level or (de)serialization error occurs opening the connection.McpException- If the server returned a JSON-RPC error for "server/discover".
-
connect
Builds a client from a caller-configured builder and performs its one mandatory handshake call, returning a ready-to-use client.If
serverDiscover()fails, the just-built client is closed before the exception propagates - a caller that only ever sees an exception fromconnect(...)never ends up owning a client (and its underlying transport resources) it has no reference to.- Parameters:
builder- The configured builder to build from. Must not benull .- Returns:
- A new client that has already completed
serverDiscover()exactly once. Nevernull . - Throws:
IOException- If a transport-level or (de)serialization error occurs opening the connection.McpException- If the server returned a JSON-RPC error for "server/discover".
-
serverDiscover
Sends "server/discover".Caches its result, so a subsequent
discoveredServer()call (including one following the mandatory discoveryconnect(Builder)already performs) does not need a repeat round trip.- Returns:
- The server-discover result. Never
null on success unless the server returns anull result. - Throws:
IOException- If a transport-level or (de)serialization error occurs.McpException- If the server returned a JSON-RPC error.
-
discoveredServer
Returns theServerDiscoverResultcached from the most recentserverDiscover()call.A client built via
connect(String)/connect(Builder)already has this populated from the mandatory handshake call, so a caller that only needs the discovery info (server capabilities, supported versions, etc.) does not need to invokeserverDiscover()again just to read it.- Returns:
- The most recently discovered server info, or
null ifserverDiscover()has not been called on this client, or the most recent call returned anull result.
-
ping
Sends "ping" to verify server liveness.- Returns:
- The ping result. Never
null on success unless the server returns anull result. - Throws:
IOException- If a transport-level or (de)serialization error occurs.McpException- If the server returned a JSON-RPC error.
-
listTools
Sends "tools/list".- Returns:
- The tools-list result. Never
null on success unless the server returns anull result. - Throws:
IOException- If a transport-level or (de)serialization error occurs.McpException- If the server returned a JSON-RPC error.
-
callTool
Sends "tools/call".- Parameters:
name- The tool name to invoke.arguments- The tool arguments. Can benull (sent as an empty object).- Returns:
- The call-tool result. Never
null on success unless the server returns anull result. - Throws:
IOException- If a transport-level or (de)serialization error occurs.McpException- If the server returned a JSON-RPC error.
-
callToolText
Convenience forcallTool(java.lang.String, java.util.Map<java.lang.String, java.lang.Object>)followed byCallToolResult.firstText().Kills the
((TextContent)result.getContent().get(i)).getText()cast-and-scan that a caller who only wants the tool's text result would otherwise repeat at every call site.- Parameters:
name- The tool name to invoke.arguments- The tool arguments. Can benull (sent as an empty object).- Returns:
- The first
TextContentblock's text found while scanning the result's content list in order, ornull if the content list is empty or unset, it contains noTextContentblock, orcallTool(java.lang.String, java.util.Map<java.lang.String, java.lang.Object>)itself returned anull result. - Throws:
IOException- If a transport-level or (de)serialization error occurs.McpException- If the server returned a JSON-RPC error.
-
listPrompts
Sends "prompts/list".- Returns:
- The prompts-list result. Never
null on success unless the server returns anull result. - Throws:
IOException- If a transport-level or (de)serialization error occurs.McpException- If the server returned a JSON-RPC error.
-
getPrompt
Sends "prompts/get".- Parameters:
name- The prompt name to fetch.arguments- The prompt argument values. Can benull (sent as an empty object).- Returns:
- The get-prompt result. Never
null on success unless the server returns anull result. - Throws:
IOException- If a transport-level or (de)serialization error occurs.McpException- If the server returned a JSON-RPC error.
-
listResources
Sends "resources/list".- Returns:
- The resources-list result. Never
null on success unless the server returns anull result. - Throws:
IOException- If a transport-level or (de)serialization error occurs.McpException- If the server returned a JSON-RPC error.
-
readResource
Sends "resources/read".- Parameters:
uri- The resource URI to read.- Returns:
- The read-resource result. Never
null on success unless the server returns anull result. - Throws:
IOException- If a transport-level or (de)serialization error occurs.McpException- If the server returned a JSON-RPC error.
-
listResourceTemplates
Sends "resources/templates/list".- Returns:
- The resource-templates-list result. Never
null on success unless the server returns anull result. - Throws:
IOException- If a transport-level or (de)serialization error occurs.McpException- If the server returned a JSON-RPC error.
-
complete
public CompleteResult complete(CompletionReference ref, String argumentName, String argumentValue, Map<String, String> contextArguments) throws IOExceptionSends "completion/complete".- Parameters:
ref- The completion target (a declared prompt or resource template reference).argumentName- The prompt argument or resource-template variable being completed.argumentValue- The current partial value ofargumentName.contextArguments- Previously-resolved argument values for context, ornull to omit thecontextobject entirely.- Returns:
- The completion result. Never
null on success unless the server returns anull result. - Throws:
IOException- If a transport-level or (de)serialization error occurs.McpException- If the server returned a JSON-RPC error.
-
callRaw
Performs a JSON-RPC call using a caller-supplied, fully-populated request bean, returning the raw result payload without deserializing into a specificResultsubtype.Every convenience method on this class (
callTool(java.lang.String, java.util.Map<java.lang.String, java.lang.Object>),getPrompt(java.lang.String, java.util.Map<java.lang.String, java.lang.Object>),readResource(java.lang.String), etc.) both builds its own request bean internally and deserializes strictly into one known result type, so none of them can represent a pausedinput_requiredresponse (MCP2026-07-28SEP-2322 Multi-Round-Trip Requests) or carry therequestState/inputResponsesfields a resume call needs to set. This method exists specifically for MRTR-aware callers that must both populate those fields on the request (e.g. on aCallToolRequest) and branch on the response'sresultTypethemselves, decoding into a typed result only onceresultTypereads"complete".- Parameters:
method- The JSON-RPC method (e.g.McpMethods.TOOLS_CALL).params- The fully-populated request bean.- Returns:
- The raw result as a generic
Map, exactly as received over the wire, before any subclass-specific deserialization. Nevernull on a successful JSON-RPC response. - Throws:
IOException- On a transport failure.McpException- If the server returns a JSON-RPC error.
-
callToolWithElicitation
public CallToolResult callToolWithElicitation(String name, Map<String, Object> arguments, McpElicitationHandler handler) throws IOExceptionInvokes "tools/call", transparently answering any MCP2026-07-28SEP-2322input_requiredelicitation pauses viahandleruntil a terminal result is reached, using thedefaultmax-rounds bound.This is the ergonomic counterpart to hand-driving the resume loop with
callRaw(java.lang.String, org.apache.juneau.bean.mcp.v20260728.RequestParams<?>),ElicitationRequests, andElicitationResponses: it detects each pause, decodes that round's requests, callshandlerfor the answers, echoes them back with the carriedrequestState, and repeats until the server returns a non-input_requiredresult, which is decoded into a typedCallToolResult.callRaw(java.lang.String, org.apache.juneau.bean.mcp.v20260728.RequestParams<?>)remains available as the low-level escape hatch.- Parameters:
name- The tool name to invoke.arguments- The tool arguments. Can benull (sent as an empty object).handler- The elicitation answer callback, invoked once per pause. Must not benull .- Returns:
- The terminal call-tool result. Never
null on success unless the server returns anull result. - Throws:
IllegalArgumentException- Ifhandlerisnull , orhandlerreturns anull result or a result map containing anull value for a requested id.IOException- If a transport-level or (de)serialization error occurs, orhandlerthrows it.McpException- If the server returned a JSON-RPC error.McpElicitationLimitException- If the server keeps pausing pastDEFAULT_MAX_ELICITATION_ROUNDS.
-
callToolWithElicitation
public CallToolResult callToolWithElicitation(String name, Map<String, Object> arguments, McpElicitationHandler handler, int maxRounds) throws IOExceptionInvokes "tools/call", transparently answering anyinput_requiredelicitation pauses viahandleruntil a terminal result is reached, bounded bymaxRounds.- Parameters:
name- The tool name to invoke.arguments- The tool arguments. Can benull (sent as an empty object).handler- The elicitation answer callback, invoked once per pause. Must not benull .maxRounds- The maximum number of resume rounds beforeMcpElicitationLimitExceptionis thrown. Must be ≥ 1.- Returns:
- The terminal call-tool result. Never
null on success unless the server returns anull result. - Throws:
IllegalArgumentException- Ifhandlerisnull ,maxRoundsis not ≥ 1, orhandlerreturns anull result or a result map containing anull value for a requested id.IOException- If a transport-level or (de)serialization error occurs, orhandlerthrows it.McpException- If the server returned a JSON-RPC error.McpElicitationLimitException- If the server keeps pausing pastmaxRounds.
-
getPromptWithElicitation
public GetPromptResult getPromptWithElicitation(String name, Map<String, Object> arguments, McpElicitationHandler handler) throws IOExceptionInvokes "prompts/get", transparently answering anyinput_requiredelicitation pauses viahandleruntil a terminal result is reached, using thedefaultmax-rounds bound.- Parameters:
name- The prompt name to fetch.arguments- The prompt argument values. Can benull (sent as an empty object).handler- The elicitation answer callback, invoked once per pause. Must not benull .- Returns:
- The terminal get-prompt result. Never
null on success unless the server returns anull result. - Throws:
IllegalArgumentException- Ifhandlerisnull , orhandlerreturns anull result or a result map containing anull value for a requested id.IOException- If a transport-level or (de)serialization error occurs, orhandlerthrows it.McpException- If the server returned a JSON-RPC error.McpElicitationLimitException- If the server keeps pausing pastDEFAULT_MAX_ELICITATION_ROUNDS.
-
getPromptWithElicitation
public GetPromptResult getPromptWithElicitation(String name, Map<String, Object> arguments, McpElicitationHandler handler, int maxRounds) throws IOExceptionInvokes "prompts/get", transparently answering anyinput_requiredelicitation pauses viahandleruntil a terminal result is reached, bounded bymaxRounds.- Parameters:
name- The prompt name to fetch.arguments- The prompt argument values. Can benull (sent as an empty object).handler- The elicitation answer callback, invoked once per pause. Must not benull .maxRounds- The maximum number of resume rounds beforeMcpElicitationLimitExceptionis thrown. Must be ≥ 1.- Returns:
- The terminal get-prompt result. Never
null on success unless the server returns anull result. - Throws:
IllegalArgumentException- Ifhandlerisnull ,maxRoundsis not ≥ 1, orhandlerreturns anull result or a result map containing anull value for a requested id.IOException- If a transport-level or (de)serialization error occurs, orhandlerthrows it.McpException- If the server returned a JSON-RPC error.McpElicitationLimitException- If the server keeps pausing pastmaxRounds.
-
readResourceWithElicitation
public ReadResourceResult readResourceWithElicitation(String uri, McpElicitationHandler handler) throws IOException Invokes "resources/read", transparently answering anyinput_requiredelicitation pauses viahandleruntil a terminal result is reached, using thedefaultmax-rounds bound.- Parameters:
uri- The resource URI to read.handler- The elicitation answer callback, invoked once per pause. Must not benull .- Returns:
- The terminal read-resource result. Never
null on success unless the server returns anull result. - Throws:
IllegalArgumentException- Ifhandlerisnull , orhandlerreturns anull result or a result map containing anull value for a requested id.IOException- If a transport-level or (de)serialization error occurs, orhandlerthrows it.McpException- If the server returned a JSON-RPC error.McpElicitationLimitException- If the server keeps pausing pastDEFAULT_MAX_ELICITATION_ROUNDS.
-
readResourceWithElicitation
public ReadResourceResult readResourceWithElicitation(String uri, McpElicitationHandler handler, int maxRounds) throws IOException Invokes "resources/read", transparently answering anyinput_requiredelicitation pauses viahandleruntil a terminal result is reached, bounded bymaxRounds.- Parameters:
uri- The resource URI to read.handler- The elicitation answer callback, invoked once per pause. Must not benull .maxRounds- The maximum number of resume rounds beforeMcpElicitationLimitExceptionis thrown. Must be ≥ 1.- Returns:
- The terminal read-resource result. Never
null on success unless the server returns anull result. - Throws:
IllegalArgumentException- Ifhandlerisnull ,maxRoundsis not ≥ 1, orhandlerreturns anull result or a result map containing anull value for a requested id.IOException- If a transport-level or (de)serialization error occurs, orhandlerthrows it.McpException- If the server returned a JSON-RPC error.McpElicitationLimitException- If the server keeps pausing pastmaxRounds.
-
listen
public McpSubscriptionHandle listen(SubscriptionFilter filter, McpSubscriptionListener listener) throws IOException Sends "subscriptions/listen", opening a managed, held-open notification stream on a background thread and dispatching decoded frames tolisteneruntil the returned handle is closed, the server completes gracefully, or the connection drops.Only the initial "subscriptions/listen" POST (opening the stream) is synchronous — a transport-level failure at that point surfaces here as a thrown
IOException. Every frame after that (the mandatoryacknowledgedframe, zero or more change notifications, and the eventual terminal frame) is decoded on a dedicated background thread and delivered tolistener; frame-processing failures surface viaMcpSubscriptionListener.onError(Throwable), never as a thrown exception from this method. This does not reusepumpNextServerMessage()(single-shot, closes its stream after at most one event) orMcpDuplexDispatcher(request/response-shaped, single registration) —listen(...)needs its own long-lived, multi-frame decode loop.- Parameters:
filter- The subscription filter (toolsListChanged/promptsListChanged/resourcesListChanged/resourceSubscriptions). Must not benull .listener- The typed callback sink. Must not benull .- Returns:
- A handle to cancel/close the subscription. Never
null . - Throws:
IOException- If the initial listen request/stream-open fails.
-
setServerRequestHandler
Registers the handler invoked for server-initiated requests delivered over the duplex event-stream channel (seeMcpDuplexDispatcher).- Parameters:
value- The handler to register. Passingnull de-registers any previously-registered handler.- Returns:
- This object.
-