Add elicitation support for server-to-client user input requests (#228)

- Add ElicitAction enum (accept/decline/cancel)
- Add schema definitions for elicitation fields (string, number, boolean, enum)
- Add ElicitationSchema wrapper for requestedSchema
- Add ElicitRequest and ElicitResult for elicitation/create method
- Update ClientCapabilities to support elicitation capability
- Add elicit() method to ClientGateway
- Store client capabilities in session during initialization
- Add comprehensive unit tests
- Add elicitation example server with book_restaurant, confirm_action, and collect_feedback tools
This commit is contained in:
Johannes Wachter 2026-02-15 23:34:19 +01:00 • committed by GitHub
commit 02e86377e4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 2582 additions and 5 deletions

View file

@ -19,6 +19,7 @@ use Mcp\Schema\Content\Content;
use Mcp\Schema\Content\ImageContent;
use Mcp\Schema\Content\SamplingMessage;
use Mcp\Schema\Content\TextContent;
use Mcp\Schema\Elicitation\ElicitationSchema;
use Mcp\Schema\Enum\LoggingLevel;
use Mcp\Schema\Enum\Role;
use Mcp\Schema\Enum\SamplingContext;
@ -30,7 +31,9 @@ use Mcp\Schema\ModelPreferences;
use Mcp\Schema\Notification\LoggingMessageNotification;
use Mcp\Schema\Notification\ProgressNotification;
use Mcp\Schema\Request\CreateSamplingMessageRequest;
use Mcp\Schema\Request\ElicitRequest;
use Mcp\Schema\Result\CreateSamplingMessageResult;
use Mcp\Schema\Result\ElicitResult;
use Mcp\Server\Session\SessionInterface;
/**
@ -158,6 +161,50 @@ class ClientGateway
return CreateSamplingMessageResult::fromArray($response->result);
}
/**
* Convenience method for elicitation requests.
*
* Requests additional information from the user via the client. The user can
* accept (providing the requested data), decline, or cancel the request.
*
* @param string $message A human-readable message describing what information is needed
* @param ElicitationSchema $requestedSchema The schema defining the fields to elicit from the user
* @param int $timeout The timeout in seconds
*
* @return ElicitResult The elicitation response containing the user's action and any provided content
*
* @throws ClientException if the client request results in an error message
*/
public function elicit(string $message, ElicitationSchema $requestedSchema, int $timeout = 120): ElicitResult
{
$request = new ElicitRequest($message, $requestedSchema);
$response = $this->request($request, $timeout);
if ($response instanceof Error) {
throw new ClientException($response);
}
return ElicitResult::fromArray($response->result);
}
/**
* Check if the connected client supports elicitation.
*
* 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 bool True if the client supports elicitation, false otherwise
*/
public function supportsElicitation(): bool
{
$capabilities = $this->session->get('client_capabilities', []);
// MCP spec: capability presence indicates support (value is typically {} or [])
return \array_key_exists('elicitation', $capabilities);
}
/**
* Send a request to the client and wait for a response (blocking).
*

View file

@ -45,6 +45,7 @@ final class InitializeHandler implements RequestHandlerInterface
\assert($request instanceof InitializeRequest);
$session->set('client_info', $request->clientInfo->jsonSerialize());
$session->set('client_capabilities', $request->capabilities->jsonSerialize());
return new Response(
$request->getId(),

View file

@ -25,6 +25,7 @@ class Session implements SessionInterface
* Official keys are:
* - initialized: bool
* - client_info: array|null
* - client_capabilities: array|null
* - protocol_version: string|null
* - log_level: string|null
*