Skip to content

Conversation

ptitjes
Copy link
Contributor

@ptitjes ptitjes commented Jul 6, 2025

Fixes #137

In this PR, I add:

  • the request and result objects for the elicitation mechanism
  • adds the client capabilities and capability checking on the client and server sides
  • adds tests to ClientTest

Motivation and Context

To support the new elicitation feature of the 2025-06-18 protocol version.

How Has This Been Tested?

I added two tests in ClientTest. The tests are not extensive yet as I only check:

  • that the server throws when the client doesn't support elicitation
  • that the client correctly handles a simple elicitation request

Maybe should I add some more tests? Please advise me.

Breaking Changes

N/A

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

  1. I was not sure whether to add the tests to ClientTest or ServerTest. (It seems to me that the tests should be divided by feature and not by client/server side, as most features involve both client and server, but I respected how it is done today.)

  2. I was not sure whether to add a method to Client to register an elicitation handler (i.e. wrap the setRequestHandler(...) call). Please advise me on what you think is best. (If that is best to add a wrapper method, maybe this can be implemented as a follow-up?)

  3. The CreateElicitationRequest.RequestedSchema class I introduced is duplicated from Tool.Input. Maybe that should be factored-out in a JsonSchema top-level class in types.kt. I was not sure you would approve that, so I did not factor it out. Please tell me if you'd prefer I factor that out. (The support for the new Tool output schema in the latest protocol version will also need the same type.)

@devcrocod devcrocod requested review from Copilot and devcrocod July 8, 2025 19:06
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Adds initial support for the new “elicitation” feature in the MCP protocol, including data types, capability checks, client/server handling, and basic tests.

  • Introduces CreateElicitationRequest and CreateElicitationResult types and updates Method.Defined
  • Adds client/server capability checks and a Server.createElicitation helper
  • Adds two new tests in ClientTest for reject and success paths

Reviewed Changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/jvmTest/kotlin/client/ClientTest.kt New tests for server-initiated elicitation accept/reject paths
src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types.kt Added elicitation types and client capability field
src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/Server.kt Added createElicitation and server-side capability assertion
src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/client/Client.kt Added client-side capability assertion for elicitation requests
api/kotlin-sdk.api Updated public API signature dump to include elicitation types
Comments suppressed due to low confidence (1)

src/jvmTest/kotlin/client/ClientTest.kt:846

  • [nitpick] Consider adding tests for the decline and cancel branches of CreateElicitationResult.Action to ensure all response paths are handled correctly.
    fun `should handle server elicitation`() = runTest {

Method.Defined.ElicitationCreate -> {
if (capabilities.elicitation == null) {
throw IllegalStateException(
"Client does not support elicitation capability (required for $method)"
Copy link
Preview

Copilot AI Jul 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The exception message is inconsistent with the server-side text and the test expectation. Consider matching it to "Client does not support elicitation (required for elicitation/create)" and use method.value rather than $method for clarity.

Suggested change
"Client does not support elicitation capability (required for $method)"
"Client does not support elicitation (required for elicitation/create)"

Copilot uses AI. Check for mistakes.

devcrocod
devcrocod previously approved these changes Jul 9, 2025
Copy link
Contributor

@devcrocod devcrocod left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your PR looks very great!

I was not sure whether to add the tests to ClientTest or ServerTest. (It seems to me that the tests should be divided by feature and not by client/server side, as most features involve both client and server, but I respected how it is done today.)

You did right. This separation will actually be helpful later on when I split sdk into server and client modules. At that point, might also revisit the tests. Additionally, we have an open issue for adding integration tests.

I was not sure whether to add a method to Client to register an elicitation handler (i.e. wrap the setRequestHandler(...) call). Please advise me on what you think is best. (If that is best to add a wrapper method, maybe this can be implemented as a follow-up?)

I think adding a dedicated method for elicitation would be a good idea. It’s not critical for this PR, but if you include it here, that would be great.

The CreateElicitationRequest.RequestedSchema class I introduced is duplicated from Tool.Input. Maybe that should be factored-out in a JsonSchema top-level class in types.kt. I was not sure you would approve that, so I did not factor it out. Please tell me if you'd prefer I factor that out. (The support for the new Tool output schema in the latest protocol version will also need the same type.)

For now, your approach looks like a good solution. I’m not sure how the spec will evolve, and having separate classes might actually help us adapt to future changes more easily. Even if it means some duplication for the time being. I think you can leave it as it is for now and consider refactoring it in a separate PR

@ptitjes
Copy link
Contributor Author

ptitjes commented Jul 11, 2025

@devcrocod Thanks a lot for your review.

I think adding a dedicated method for elicitation would be a good idea. It’s not critical for this PR, but if you include it here, that would be great.

OK, I can add that in this PR. Would an setElicitationHandler method of the following shape be good for you?

fun Client.setElicitationHandler(handler: (CreateElicitationRequest) -> CreateElicitationResult) { /* ... */ }

I’m not sure how the spec will evolve, and having separate classes might actually help us adapt to future changes more easily.

That makes sense!

@ptitjes ptitjes force-pushed the feature/add-elicitation branch from 97f8c07 to 3865234 Compare July 11, 2025 07:54
@ptitjes
Copy link
Contributor Author

ptitjes commented Jul 11, 2025

Added the new method and rebased on main.

@ptitjes ptitjes requested a review from devcrocod July 11, 2025 08:58
Copy link
Contributor

@devcrocod devcrocod left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@devcrocod devcrocod enabled auto-merge (squash) July 11, 2025 12:37
@devcrocod devcrocod merged commit 675cc73 into modelcontextprotocol:main Jul 11, 2025
1 check passed
@ptitjes ptitjes deleted the feature/add-elicitation branch July 11, 2025 13:45
svc-squareup-copybara pushed a commit to cashapp/misk that referenced this pull request Aug 18, 2025
| Package | Type | Package file | Manager | Update | Change |
|---|---|---|---|---|---|
|
[io.modelcontextprotocol:kotlin-sdk](https://github.com/modelcontextprotocol/kotlin-sdk)
| dependencies | misk/gradle/libs.versions.toml | gradle | minor |
`0.5.0` -> `0.6.0` |
|
[org.jetbrains.kotlinx:kotlinx-serialization-json](https://github.com/Kotlin/kotlinx.serialization)
| dependencies | misk/gradle/libs.versions.toml | gradle | minor |
`1.7.3` -> `1.9.0` |
|
[org.jetbrains.kotlinx:kotlinx-serialization-core](https://github.com/Kotlin/kotlinx.serialization)
| dependencies | misk/gradle/libs.versions.toml | gradle | minor |
`1.7.3` -> `1.9.0` |
|
[com.google.apis:google-api-services-storage](http://nexus.sonatype.org/oss-repository-hosting.html)
([source](http://svn.sonatype.org/spice/tags/oss-parent-7)) |
dependencies | misk/gradle/libs.versions.toml | gradle | patch |
`v1-rev20250718-2.0.0` -> `v1-rev20250814-2.0.0` |
| [software.amazon.awssdk:sdk-core](https://aws.amazon.com/sdkforjava) |
dependencies | misk/gradle/libs.versions.toml | gradle | patch |
`2.32.23` -> `2.32.24` |
| [software.amazon.awssdk:sqs](https://aws.amazon.com/sdkforjava) |
dependencies | misk/gradle/libs.versions.toml | gradle | patch |
`2.32.23` -> `2.32.24` |
| [software.amazon.awssdk:regions](https://aws.amazon.com/sdkforjava) |
dependencies | misk/gradle/libs.versions.toml | gradle | patch |
`2.32.23` -> `2.32.24` |
|
[software.amazon.awssdk:dynamodb-enhanced](https://aws.amazon.com/sdkforjava)
| dependencies | misk/gradle/libs.versions.toml | gradle | patch |
`2.32.23` -> `2.32.24` |
| [software.amazon.awssdk:dynamodb](https://aws.amazon.com/sdkforjava) |
dependencies | misk/gradle/libs.versions.toml | gradle | patch |
`2.32.23` -> `2.32.24` |
| [software.amazon.awssdk:aws-core](https://aws.amazon.com/sdkforjava) |
dependencies | misk/gradle/libs.versions.toml | gradle | patch |
`2.32.23` -> `2.32.24` |
| [software.amazon.awssdk:bom](https://aws.amazon.com/sdkforjava) |
dependencies | misk/gradle/libs.versions.toml | gradle | patch |
`2.32.23` -> `2.32.24` |
| [software.amazon.awssdk:auth](https://aws.amazon.com/sdkforjava) |
dependencies | misk/gradle/libs.versions.toml | gradle | patch |
`2.32.23` -> `2.32.24` |

---

### Release Notes

<details>
<summary>modelcontextprotocol/kotlin-sdk
(io.modelcontextprotocol:kotlin-sdk)</summary>

###
[`v0.6.0`](https://github.com/modelcontextprotocol/kotlin-sdk/releases/tag/0.6.0)

[Compare
Source](modelcontextprotocol/kotlin-sdk@0.5.0...0.6.0)

#### What's Changed

- Update jreleaser to fix publication issue by
[@&#8203;e5l](https://github.com/e5l) in
modelcontextprotocol/kotlin-sdk#91
- Disable configuration cache to fix jreleaser issue by
[@&#8203;e5l](https://github.com/e5l) in
modelcontextprotocol/kotlin-sdk#92
- feat: Add audio type according to 2025-03-26 spec by
[@&#8203;SeanChinJunKai](https://github.com/SeanChinJunKai) in
modelcontextprotocol/kotlin-sdk#68
- fix(client): serialize inputSchema as input\_schema by
[@&#8203;shiqicao](https://github.com/shiqicao) in
modelcontextprotocol/kotlin-sdk#97
- fix(client) add encodeDefault for field with non spec default value by
[@&#8203;shiqicao](https://github.com/shiqicao) in
modelcontextprotocol/kotlin-sdk#99
- Make McpJson public to allow flexible protocol development by
[@&#8203;parnurzeal](https://github.com/parnurzeal) in
modelcontextprotocol/kotlin-sdk#103
- fix: apply `requestBuilder` headers when sending rpc messages by
[@&#8203;dead8309](https://github.com/dead8309) in
modelcontextprotocol/kotlin-sdk#96
- fix: Remove [@&#8203;SerialName](https://github.com/SerialName)
annotation for inputSchema by
[@&#8203;adamglin0](https://github.com/adamglin0) in
modelcontextprotocol/kotlin-sdk#105
- add ios and wasm targets by
[@&#8203;devcrocod](https://github.com/devcrocod) in
modelcontextprotocol/kotlin-sdk#81
- Add dependabot by [@&#8203;StefMa](https://github.com/StefMa) in
modelcontextprotocol/kotlin-sdk#121
- Bump org.jetbrains.kotlinx:kotlinx-serialization-json from 1.7.3 to
1.8.1 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in
modelcontextprotocol/kotlin-sdk#127
- Bump io.github.oshai:kotlin-logging from 7.0.0 to 7.0.7 by
[@&#8203;dependabot](https://github.com/dependabot)\[bot] in
modelcontextprotocol/kotlin-sdk#126
- Bump org.jetbrains.kotlinx.binary-compatibility-validator from 0.17.0
to 0.18.0 by [@&#8203;dependabot](https://github.com/dependabot)\[bot]
in modelcontextprotocol/kotlin-sdk#125
- update kotlin to 2.2.0 and ktor to 3.1.3 by
[@&#8203;devcrocod](https://github.com/devcrocod) in
modelcontextprotocol/kotlin-sdk#120
- Add client roots addition/removal API and listRoots handler by
[@&#8203;ptitjes](https://github.com/ptitjes) in
modelcontextprotocol/kotlin-sdk#118
- Bump org.slf4j:slf4j-simple from 2.0.16 to 2.0.17 by
[@&#8203;dependabot](https://github.com/dependabot)\[bot] in
modelcontextprotocol/kotlin-sdk#131
- Bump org.jetbrains.kotlinx:kotlinx-serialization-json from 1.8.1 to
1.9.0 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in
modelcontextprotocol/kotlin-sdk#132
- Bump io.mockk:mockk from 1.13.13 to 1.14.4 by
[@&#8203;dependabot](https://github.com/dependabot)\[bot] in
modelcontextprotocol/kotlin-sdk#133
- Remove fixed suffix /sse by
[@&#8203;adamglin0](https://github.com/adamglin0) in
modelcontextprotocol/kotlin-sdk#108
- sse server does not process endpoint correctly when sse path is not a
directory by [@&#8203;shendaxia-sm](https://github.com/shendaxia-sm) in
modelcontextprotocol/kotlin-sdk#43
- Add labels to dependabot configuration for Kotlin and GitHub Actions
by [@&#8203;devcrocod](https://github.com/devcrocod) in
modelcontextprotocol/kotlin-sdk#135
- feat: add tool annotations according to 2025-03-26 spec by
[@&#8203;SeanChinJunKai](https://github.com/SeanChinJunKai) in
modelcontextprotocol/kotlin-sdk#71
- Bump ktor from 3.1.3 to 3.2.1 by
[@&#8203;dependabot](https://github.com/dependabot)\[bot] in
modelcontextprotocol/kotlin-sdk#140
- Bump gradle/actions from 4.0.0 to 4.4.1 by
[@&#8203;dependabot](https://github.com/dependabot)\[bot] in
modelcontextprotocol/kotlin-sdk#122
- Bump org.jreleaser from 1.17.0 to 1.19.0 by
[@&#8203;dependabot](https://github.com/dependabot)\[bot] in
modelcontextprotocol/kotlin-sdk#141
- refactor `SseClientTransport` by
[@&#8203;devcrocod](https://github.com/devcrocod) in
modelcontextprotocol/kotlin-sdk#142
- atomic and persistent collections for thread safety by
[@&#8203;devcrocod](https://github.com/devcrocod) in
modelcontextprotocol/kotlin-sdk#143
- Bump org.gradle.toolchains.foojay-resolver-convention from 0.8.0 to
1.0.0 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in
modelcontextprotocol/kotlin-sdk#130
- Add support for elicitation by
[@&#8203;ptitjes](https://github.com/ptitjes) in
modelcontextprotocol/kotlin-sdk#138
- Add support for tool structured content and output schema by
[@&#8203;ptitjes](https://github.com/ptitjes) in
modelcontextprotocol/kotlin-sdk#146
- Add streamable http client transport by
[@&#8203;devcrocod](https://github.com/devcrocod) in
modelcontextprotocol/kotlin-sdk#147
- Refactor JSON processing to exclude "method" in serialization by
[@&#8203;devcrocod](https://github.com/devcrocod) in
[#&#8203;157](modelcontextprotocol/kotlin-sdk#157)
- Release 0.6.0 by [@&#8203;devcrocod](https://github.com/devcrocod) in
modelcontextprotocol/kotlin-sdk#149

#### New Contributors

- [@&#8203;shiqicao](https://github.com/shiqicao) made their first
contribution in
modelcontextprotocol/kotlin-sdk#97
- [@&#8203;parnurzeal](https://github.com/parnurzeal) made their first
contribution in
modelcontextprotocol/kotlin-sdk#103
- [@&#8203;dead8309](https://github.com/dead8309) made their first
contribution in
modelcontextprotocol/kotlin-sdk#96
- [@&#8203;adamglin0](https://github.com/adamglin0) made their first
contribution in
modelcontextprotocol/kotlin-sdk#105
- [@&#8203;StefMa](https://github.com/StefMa) made their first
contribution in
modelcontextprotocol/kotlin-sdk#121
- [@&#8203;dependabot](https://github.com/dependabot)\[bot] made their
first contribution in
modelcontextprotocol/kotlin-sdk#127
- [@&#8203;ptitjes](https://github.com/ptitjes) made their first
contribution in
modelcontextprotocol/kotlin-sdk#118
- [@&#8203;shendaxia-sm](https://github.com/shendaxia-sm) made their
first contribution in
modelcontextprotocol/kotlin-sdk#43

**Full Changelog**:
modelcontextprotocol/kotlin-sdk@0.5.0...0.6.0

</details>

<details>
<summary>Kotlin/kotlinx.serialization
(org.jetbrains.kotlinx:kotlinx-serialization-json)</summary>

###
[`v1.9.0`](https://github.com/Kotlin/kotlinx.serialization/blob/HEAD/CHANGELOG.md#190--2025-06-27)

\==================

This release updates Kotlin version to 2.2.0, includes several bugfixes
and provides serializers for kotlin.time.Instant.

#### Add kotlin.time.Instant serializers

Instant class was moved from kotlinx-datetime library to Kotlin standard
library.
As a result, kotlinx-datetime 0.7.0 no longer has serializers for the
Instant class.
To use new kotlin.time.Instant class in your
[@&#8203;Serializable](https://github.com/Serializable) classes,
you can use this 1.9.0 kotlinx-serialization version (Kotlin 2.2 is
required).
You can choose between default `InstantSerializer` which uses its string
representation,
or specify `InstantComponentSerializer` that represents instant as its
components.
See details in the
[PR](Kotlin/kotlinx.serialization#2945).

#### Other bugfixes

- Fix resize in JsonPath
([#&#8203;2995](Kotlin/kotlinx.serialization#2995))
- Fixed proguard rules for obfuscation to work correctly
([#&#8203;2983](Kotlin/kotlinx.serialization#2983))

###
[`v1.8.1`](https://github.com/Kotlin/kotlinx.serialization/blob/HEAD/CHANGELOG.md#181--2025-03-31)

\==================

This release updates Kotlin version to 2.1.20, while also providing
several important improvements
and bugfixes.

#### Improvements

- Implemented encoding null in key and value of a map in Protobuf
([#&#8203;2910](Kotlin/kotlinx.serialization#2910))
- Make type argument in JsonTransformingSerializer nullable
([#&#8203;2911](Kotlin/kotlinx.serialization#2911))
- Use SPDX identifier in POMs
([#&#8203;2936](Kotlin/kotlinx.serialization#2936))
(thanks to [Leon Linhart](https://github.com/TheMrMilchmann))
- Add watchosDeviceArm64 to Okio integration module
([#&#8203;2920](Kotlin/kotlinx.serialization#2920))
(thanks to [Daniel Santiago](https://github.com/danysantiago))
- Update kotlinx-io version to 0.6.0
([#&#8203;2933](Kotlin/kotlinx.serialization#2933))
(thanks to [Piotr Krzemiński](https://github.com/krzema12))

#### Bugfixes

- Fix incorrect enum coercion during deserialization from JsonElement
([#&#8203;2962](Kotlin/kotlinx.serialization#2962))
- Supply proper equals(), hashCode(), and toString() for
SerialDescriptor() wrapper
([#&#8203;2942](Kotlin/kotlinx.serialization#2942))
- Do not encode empty packed collections in protobuf
([#&#8203;2907](Kotlin/kotlinx.serialization#2907))

###
[`v1.8.0`](https://github.com/Kotlin/kotlinx.serialization/blob/HEAD/CHANGELOG.md#180--2025-01-06)

\==================

This release contains all of the changes from 1.8.0-RC. Kotlin 2.1.0 is
used as a default, while upcoming 2.1.10 is also supported.
Also added small bugfixes, including speedup of ProtoWireType.from
([#&#8203;2879](Kotlin/kotlinx.serialization#2879)).

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "after 6pm every weekday,before 2am
every weekday" in timezone Australia/Melbourne, Automerge - At any time
(no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Never, or you tick the rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config help](https://github.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Renovate
Bot](https://github.com/renovatebot/renovate).

GitOrigin-RevId: 40e2f07ecd958e92e64c571d1351e91f96e71ce7
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support Elicitation
2 participants