MCP PHP SDK

ClientGateway

Tags
final

Helper class for tools to communicate with the client.

This class provides a clean API for element handlers to send requests and notifications to the client. It uses PHP Fibers internally to make the communication appear synchronous while the transport handles all blocking operations.

Example usage in a tool:

public function analyze(string $text, RequestContext $context): string {
    $client = $context->getClientGateway();
    // Send progress notification
    $client->notify(new ProgressNotification("Starting analysis..."));

    // Request LLM sampling from client
    $result = $client->sample($text);

    return $result->content->text;
}
author

Kyrian Obikwelu koshnawaza@gmail.com

Table of Contents

Properties

$session  : SessionInterface

Methods

__construct()  : mixed
elicit()  : ElicitResult
Convenience method for form-mode elicitation requests.
elicitUrl()  : ElicitResult
Convenience method for url-mode elicitation requests.
listRoots()  : ListRootsResult
Request the list of filesystem roots exposed by the client.
log()  : void
Convenience method to send a logging notification to the client.
notify()  : void
Send a notification to the client (fire and forget).
progress()  : void
Convenience method to send a progress notification to the client.
sample()  : CreateSamplingMessageResult
Convenience method for LLM sampling requests.
supportsElicitation()  : bool
Check if the connected client supports elicitation.
supportsElicitationUrl()  : bool
Check if the connected client supports url-mode elicitation.
supportsExtension()  : bool
Check if the connected client negotiated the given protocol extension.
supportsRoots()  : bool
Check if the connected client supports roots.
supportsSampling()  : bool
Check if the connected client supports sampling.
supportsSamplingContext()  : bool
Check if the connected client supports context inclusion during sampling.
supportsSamplingTools()  : bool
Check if the connected client supports tools during sampling.
hasSubCapability()  : bool
Sub-capabilities are declared by the presence of a (possibly empty) object, so only the key matters — not whatever it holds. The value arrives as an object on a live session and as an array once the session has round-tripped through JSON, hence both shapes.
sendElicitation()  : ElicitResult
suspend()  : Response<string|int, array<string, mixed>>|Error
Hands the request to whatever is driving this fiber and waits for its answer.

Properties

Methods

elicit()

Convenience method for form-mode elicitation requests.

public elicit(string $message, ElicitationSchema $requestedSchema[, int $timeout = 120 ][, string|null $key = null ]) : ElicitResult

Requests additional information from the user via the client. The user can accept (providing the requested data), decline, or cancel the request.

Serves every revision, by two different mechanics. Where the client can be asked while the request is open, it is: an elicitation/create goes out and this call returns its answer. From 2026-07-28 on there are no server-initiated requests, so the ask ends the request instead and the call returns once the client re-sends it with the answer — see ElicitationReplay for what that costs, namely that the handler is entered once per ask.

Parameters
$message : string

A human-readable message describing what information is needed

$requestedSchema : ElicitationSchema

The schema defining the fields to elicit from the user

$timeout : int = 120

The timeout in seconds; unused where the answer arrives on a later request

$key : string|null = null

Names this ask, so it keeps resolving to the same answer across the rounds a revision without server-initiated requests needs. Defaults to the ask's position in the handler, which only a handler asking in a different order every time needs to override.

Tags
throws
ClientException

if the client request results in an error message

Return values
ElicitResult

The elicitation response containing the user's action and any provided content

elicitUrl()

Convenience method for url-mode elicitation requests.

public elicitUrl(string $message, string $url[, int $timeout = 120 ][, string|null $key = null ]) : ElicitResult

Sends the user to $url to complete the interaction out of band — an OAuth consent screen, a checkout, a form hosted elsewhere. The result carries only the user's action; unlike form mode there is no content to read back, so whatever the user did there has to be picked up through the URL's own channel.

Portable across revisions on the same terms as self::elicit().

Parameters
$message : string
$url : string
$timeout : int = 120
$key : string|null = null

names this ask across the rounds of a multi round-trip call

Tags
throws
ClientException

if the client request results in an error message

InvalidArgumentException

if the client did not declare url-mode elicitation

Return values
ElicitResult

listRoots()

Request the list of filesystem roots exposed by the client.

public listRoots([int $timeout = 120 ]) : ListRootsResult

since protocol revision 2026-07-28 (SEP-2577), earliest removal 2027-07-28. Pass directories or files through tool arguments, resource URIs or server configuration instead.

Roots are the client's "workspace folders" — the directories or files the server is allowed to operate on. The client answers the roots/list request with a list of file:// URIs.

Parameters
$timeout : int = 120

The timeout in seconds

Tags
throws
ClientException

if the client request results in an error message

Return values
ListRootsResult

The roots exposed by the client

log()

Convenience method to send a logging notification to the client.

public log(LoggingLevel $level, mixed $data[, string|null $logger = null ]) : void

since protocol revision 2026-07-28 (SEP-2577), earliest removal 2027-07-28. Log to stderr (stdio) or use OpenTelemetry instead.

Parameters
$level : LoggingLevel
$data : mixed
$logger : string|null = null

notify()

Send a notification to the client (fire and forget).

public notify(Notification $notification) : void

This suspends the Fiber to let the transport flush the notification via SSE, then immediately resumes execution.

Parameters
$notification : Notification

progress()

Convenience method to send a progress notification to the client.

public progress(float $progress[, float|null $total = null ][, string|null $message = null ]) : void
Parameters
$progress : float
$total : float|null = null
$message : string|null = null

sample()

Convenience method for LLM sampling requests.

public sample(array<string|int, SamplingMessage>|TextContent|AudioContent|ImageContent|string $message[, int $maxTokens = 1000 ][, int $timeout = 120 ][, SampleOptions $options = [] ]) : CreateSamplingMessageResult

since protocol revision 2026-07-28 (SEP-2577), earliest removal 2027-07-28. Integrate with an LLM provider's API directly instead.

Parameters
$message : array<string|int, SamplingMessage>|TextContent|AudioContent|ImageContent|string

The message for the LLM

$maxTokens : int = 1000

Maximum tokens to generate

$timeout : int = 120

The timeout in seconds

$options : SampleOptions = []

Additional sampling options (temperature, etc.) Context values other than none require the client's sampling.context capability; tools and toolChoice require the client's sampling.tools capability.

Tags
throws
ClientException

if the client request results in an error message

Return values
CreateSamplingMessageResult

The sampling response

supportsElicitation()

Check if the connected client supports elicitation.

public supportsElicitation() : bool

Elicitation allows servers to request additional information from users during tool execution. This method checks the client's advertised capabilities to determine if elicitation/create requests are supported.

Return values
bool

True if the client supports elicitation, false otherwise

supportsElicitationUrl()

Check if the connected client supports url-mode elicitation.

public supportsElicitationUrl() : bool

An elicitation capability naming no mode declares form mode — the only shape that existed before URL elicitation — so url mode has to be named explicitly.

Return values
bool

True if the client supports url-mode elicitation, false otherwise

supportsExtension()

Check if the connected client negotiated the given protocol extension.

public supportsExtension(ExtensionIdentifier|string $id) : bool

Extensions are advertised under capabilities.extensions keyed by their reverse-DNS id, e.g. McpApps::EXTENSION_ID — a server offering MCP Apps should check this before pointing a tool at a ui:// resource, and fall back to a text-only result otherwise.

Parameters
$id : ExtensionIdentifier|string
Return values
bool

True if the client advertised the extension, false otherwise

supportsRoots()

Check if the connected client supports roots.

public supportsRoots() : bool

Roots allow servers to ask the client for the set of directories or files it is permitted to operate on. This method checks the client's advertised capabilities to determine if roots/list requests are supported.

Return values
bool

True if the client supports roots, false otherwise

supportsSampling()

Check if the connected client supports sampling.

public supportsSampling() : bool

Sampling lets a server borrow the client's model during tool execution. This method checks the client's advertised capabilities to determine if sampling/createMessage requests are supported.

Return values
bool

True if the client supports sampling, false otherwise

supportsSamplingContext()

Check if the connected client supports context inclusion during sampling.

public supportsSamplingContext() : bool

The includeContext values other than none are soft-deprecated and should only be sent when the client advertised sampling.context.

Return values
bool

True if the client supports sampling context, false otherwise

supportsSamplingTools()

Check if the connected client supports tools during sampling.

public supportsSamplingTools() : bool

Per the spec a server MUST NOT put tools or toolChoice on a sampling/createMessage request unless the client advertised sampling.tools, so check this before passing either option to self::sample().

Return values
bool

True if the client supports tool-enabled sampling, false otherwise

hasSubCapability()

Sub-capabilities are declared by the presence of a (possibly empty) object, so only the key matters — not whatever it holds. The value arrives as an object on a live session and as an array once the session has round-tripped through JSON, hence both shapes.

private hasSubCapability(string $capability, string $name) : bool
Parameters
$capability : string
$name : string
Return values
bool

suspend()

Hands the request to whatever is driving this fiber and waits for its answer.

private suspend(Request $request, int $timeout[, string|null $key = null ]) : Response<string|int, array<string, mixed>>|Error
Parameters
$request : Request
$timeout : int
$key : string|null = null

the name an elicitation's answer is filed under when the revision serving this call answers by asking (ElicitationReplay); ignored by every leg that has a live client to ask

Return values
Response<string|int, array<string, mixed>>|Error

the peer's answer

On this page

Search results