feat: add MCP elicitation support (form + URL modes)#190
feat: add MCP elicitation support (form + URL modes)#190datashaman wants to merge 10 commits intolaravel:mainfrom
Conversation
Implement the MCP 2025-11-25 elicitation specification, allowing servers to request additional information from users mid-tool-execution. Adds an injectable Elicitation service with form mode (structured data via JSON Schema) and URL mode (external redirects for OAuth/payments), fluent schema builders, client capability detection, and testing assertions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Thanks for submitting a PR! Note that draft PRs are not reviewed. If you would like a review, please mark your pull request as ready for review in the GitHub user interface. Pull requests that are abandoned in draft may be closed due to inactivity. |
…ntract Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ansport routing - Improve 3 error messages with cause + fix guidance - Add ElicitationSent and ElicitationReceived Laravel events - Advertise elicitation capability in server initialize response - Add clientCapabilities() to Transport interface, remove FakeTransporter coupling - Extract AbstractElicitField base class, add isRequired() to interface - Route elicitation responses to cache for HttpTransport polling (P1 fix) - Add cache cleanup on timeout, cache TTL on writes - Add ID mismatch test, update field tests for isRequired() Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Apply SafeDeclareStrictTypesRector, ClosureToArrowFunctionRector, and AddArrowFunctionReturnTypeRector fixes. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Cast json_encode returns in FakeTransporter to string - Remove redundant null coalescing on stream_get_meta_data keys - Add array cast for nullable titledOptions in foreach loops Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Extract elicitations() helper in TestResponse, reorder properties in PendingTestResponse, deduplicate json_decode in FakeTransporter, and add missing strict_types declarations to test files. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ity key Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…method Merge withElicitation() and expectsElicitation() into elicitation() on PendingTestResponse. Use CAPABILITY_ELICITATION constant consistently. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Only FakeTransporter used it meaningfully; real transports returned null. Capabilities now flow through Server::$clientCapabilities exclusively. PendingTestResponse injects capabilities via ->call() pattern. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Hi before I start the review, could you confirm you’ve tested this locally and it works? The entire PR looks AI-generated and as this is a very large PR I don’t just want to jump in and review it. Could you please double-check? |
|
I've tested that elicitation works with STDIO mode in Claude Code. |
|
Hmm, I have not given it a runthrough via MCP Inspector. Please hold off on reviewing this until I get back to you. That will support everything. |
|
The MCP Inspector does not support HTTP elicitations. |

Summary
Elicitationservice withform()(structured JSON Schema data collection) andurl()(external redirects for OAuth/payments) modesUrlElicitationRequiredException(-32042), completion notifications, and full testing assertionsUsage
Changes
New files (13 source, 5 test):
src/Server/Elicitation/Elicitation.php— injectable service with event dispatchingsrc/Server/Elicitation/ElicitationResult.php— response value objectsrc/Server/Elicitation/ElicitSchema.php— fluent schema buildersrc/Server/Elicitation/UrlElicitationRequiredException.php— error code -32042src/Server/Elicitation/Events/ElicitationSent.php— dispatched on elicitation requestsrc/Server/Elicitation/Events/ElicitationReceived.php— dispatched on responsesrc/Server/Elicitation/Fields/— ElicitField interface + AbstractElicitField base + 6 field classestests/Unit/Elicitation/— 4 unit test filestests/Feature/Testing/Tools/AssertElicitationTest.php— integration testsModified files (8):
src/Server/Contracts/Transport.php— addedsendRequest()methodsrc/Server/Transport/StdioTransport.php— blocking stdin implementationsrc/Server/Transport/HttpTransport.php— SSE + cache polling implementationsrc/Server/Transport/FakeTransporter.php— expectation queue + sent trackingsrc/Server/Transport/JsonRpcResponse.php— added::request()factorysrc/Server.php— elicitation capability, response routing, Elicitation container bindingsrc/Server/Testing/PendingTestResponse.php—elicitation()test setup methodsrc/Server/Testing/TestResponse.php— elicitation assertion methodsTest plan
🤖 Generated with Claude Code