NAME
AnyEvent::MCP::Client - asynchronous MCP client protocol
SYNOPSIS
use AnyEvent::MCP::Client::HTTP;
my $client = AnyEvent::MCP::Client::HTTP->new (
url => $url, bearer => $token,
);
$client->call (echo => { text => "hello" }, sub {
my ($success, $result) = @_;
...
});
DESCRIPTION
This is the common protocol implementation used by AnyEvent::MCP::Client::HTTP and AnyEvent::MCP::Client::JSONL. Choose a transport, keep the client object alive, and run an AnyEvent event loop. You can call a tool without connecting explicitly: the client connects and discovers or initializes the server as needed. Concurrent requests share that work instead of starting independent connections.
An interrupted connection does not mean the server did nothing. A tool might have completed its side effects just before the connection failed. For that reason, the client never replays a tool call automatically. Applications that want retries must decide whether the operation is safe to repeat.
Modern clients use discovery and per-request metadata. Legacy clients use initialization and ordinary request/response. Legacy server-initiated requests are accepted on JSONL; legacy HTTP GET streams are not implemented.
For a runnable call, see "FIRST CALL" in AnyEvent::MCP::Client::HTTP when connecting to an HTTP endpoint or "FIRST CALL" in AnyEvent::MCP::Client::JSONL when launching a subprocess. Both use call from this module. In its callback, $success reports JSON-RPC/transport success; a tool can still return isError true. Keep the client alive while its callbacks are pending.
METHODS
- $client = AnyEvent::MCP::Client->new (%config)
-
Normally construct a transport subclass. Its constructor accepts these common options as well as the transport-specific options:
- client_info => { name => $name, version => $version }
-
Advertised client identity. Defaults to
AnyEvent::MCPand this distribution's version. - client_capabilities => { %capabilities }
-
Supported client interactions, defaulting to an empty hash. Advertising a capability does not install a handler; supply
on_requestwhen needed. - versions => [$version...]
-
Supported protocol revisions in preference order. Defaults to
2026-07-28,2025-11-25,2025-06-18and2025-03-26. Here, modern means the 2026 discovery/input-challenge protocol; legacy means the 2025 initialization protocol. - request_timeout => $seconds
-
Optional overall deadline for
rpcandcall, including connection and user input. Omitted or zero means no overall deadline. This is separate from HTTP's inactivity timeout. - max_rounds => $count
-
Maximum input-challenge rounds handled by
call, defaulting to 32. - name => $name
-
Optional local configuration name, independent of
client_info. HTTP loads[client NAME]defaults only when this is supplied; JSONL does not load transport defaults.
Event callbacks are also constructor options; see "EVENTS".
- $client->connect ($done->($success, $result))
-
Discovers or initializes the server. On success
$resultis undef. Any JSON-RPC error from discovery falls back to legacy initialization. Transport failures do not trigger fallback. After connecting,protocol_version,server_info,server_capabilitiesandinstructionsare available directly in the client hash. - $id = $client->rpc ($method, $params, $done->($success, $result))
-
Sends a request.
$paramsis a hash reference and is not modified.$ididentifies the local operation for cancellation. Callbacks may run before this method returns.On success
$resultis the entire decoded result, includingisError,_metaandresultType. A result withresultTypeset toinput_requiredis returned unchanged.$successreports whether the JSON-RPC request succeeded, not whether the tool succeeded: a tool result withisErrortrue still has$successtrue. On failure$resultis an error hash: JSON-RPC errors retain their fields, while local errors havemessageandtransporttrue. Local cancellation also hascancelledtrue. Each completion callback runs once. - $id = $client->call ($name, $args, $done->($success, $result), %params)
-
Calls a tool and handles modern
input_requiredresults viaon_request.$argsis a hash reference of tool arguments.%paramssupplies additional protocol parameters, such as_meta. Set$params{_meta}{"io.modelcontextprotocol/clientCapabilities"}to override the constructor capabilities for this call, allowing brokers to advertise the upstream capabilities without changing shared state. The original method and arguments are retained; only server-requested answers and opaquerequestStateare added for continuation. No connection failure causes a retry. Withouton_request, an interaction fails locally.Permission challenges are input requests handled by
on_request. To ask locally through the external permission helper:client_capabilities => { elicitation => { form => {} } }, on_request => sub { AnyEvent::MCP::Permissions::Ask->elicitation ($_[1]); },Load AnyEvent::MCP::Permissions::Ask before using that callback. It handles permission-tagged elicitation only; applications supporting other elicitation requests dispatch those separately. The client does not silently approve permissions.
rpcreturns input challenges intact for broker forwarding. - $client->tools ($done->($success, $tools))
-
Collects all pages of tool definitions into an array reference. Names and definitions are preserved. Repeated pagination cursors are rejected.
- $client->notify ($method, $params, $done->($success, $result))
-
Sends a notification after connecting.
$doneis optional. Success means the transport accepted it, not that the server acted on it. - $client->cancel ($id, $reason)
-
Cancels a pending local operation, completes its callback with an error and sends best-effort protocol cancellation for an outstanding wire request.
$reasonis optional. Late responses are ignored. - $client->close
-
Closes transport resources, cancels input handlers and fails pending callbacks. New operations can reconnect. Previously sent calls are not repeated.
EVENTS
- on_request => $callback->($client, $req)
-
Handles an input request asynchronously.
$reqis a AnyEvent::MCP::Client::Request withmethodandparams. Declare the corresponding capabilities explicitly inclient_capabilities. For a broker,rpccan instead return the complete input challenge upstream. - on_notification => $callback->($client, $method, $params)
-
Receives server notifications, including progress and tool-list changes.
- on_ready => $callback->($client)
-
Called once after a successful MCP discovery or initialization, including reconnections. It does not fire for repeated
connectcalls on an already connected client. - on_close => $callback->($client, $error)
-
Called when an established connection closes unexpectedly, with a transport error hash.
pendingcounts operations interrupted by the close, before their callbacks were failed. An explicitclosewithout a reason does not trigger this event.