feat(server): accept Standard Schemas for elicitation#2369
Conversation
🦋 Changeset detectedLatest commit: 12eb9e5 The changes in this PR will be included in the next version bump. This PR includes changesets to release 7 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
@modelcontextprotocol/client
@modelcontextprotocol/codemod
@modelcontextprotocol/core
@modelcontextprotocol/server
@modelcontextprotocol/server-legacy
@modelcontextprotocol/express
@modelcontextprotocol/fastify
@modelcontextprotocol/hono
@modelcontextprotocol/node
commit: |
01f43f4 to
f732d6f
Compare
ea55f4b to
1308739
Compare
918c601 to
a300f51
Compare
7908e11 to
15e6243
Compare
15e6243 to
12eb9e5
Compare
felixweinberger
left a comment
There was a problem hiding this comment.
Mostly wondering if we should be updating the elicitInput API given we want people to use inputRequired for MRTR going forward.
| * both eras, this only works on the legacy path. | ||
| */ | ||
| elicitInput: (params: ElicitRequestFormParams | ElicitRequestURLParams, options?: RequestOptions) => Promise<ElicitResult>; | ||
| elicitInput: { |
There was a problem hiding this comment.
This is deprecated API, we don't really want people to continue you building on this, but consolidate on the inputRequired form - there's a backwards compatibility shim that allows people to write the MRTR based elicitation but still serve 2025-11-25 based servers with it.
Given that, I feel like we should instead mark this API @deprecated and not take on the effort of making it StandardSchema compatible.
There was a problem hiding this comment.
That would also remove the need for the overload introduced further down.
| * @param options Optional request options. | ||
| * @returns The result of the elicitation request. | ||
| * | ||
| * @deprecated Throws on a 2026-07-28-era request — use {@link index.inputRequired | inputRequired} (multi-round-trip) |
There was a problem hiding this comment.
Ah I see it's already marked deprecated here - rather than make it compatible with standard schema should we keep it simple and leave this out and push people to use inputRequired if they want to use standardSchema?
| export const inputRequired: InputRequiredBuilder = Object.assign(buildInputRequired, { | ||
| elicit(params: Omit<ElicitRequestFormParams, 'mode'> & { mode?: 'form' }): InputRequest { | ||
| return { method: 'elicitation/create', params: { ...params, mode: 'form' } }; | ||
| elicit( | ||
| params: | ||
| | (Omit<ElicitRequestFormParams, 'mode'> & { mode?: 'form' }) | ||
| | (Omit<ElicitInputFormParams<StandardSchemaWithJSON>, 'mode'> & { mode?: 'form' }) | ||
| ): InputRequest { | ||
| const { params: normalizedParams } = normalizeElicitInputFormParams( | ||
| params as ElicitRequestFormParams | ElicitInputFormParams<StandardSchemaWithJSON> | ||
| ); | ||
| return { method: 'elicitation/create', params: normalizedParams }; |
There was a problem hiding this comment.
I believe this could be cleaned up with something like this?
elicit(params: ElicitInputParams): InputRequest {
try {
const { params: normalizedParams } = normalizeElicitInputFormParams(params);
return { method: 'elicitation/create', params: normalizedParams };
} catch (error) {
throw error instanceof ProtocolError ? new TypeError(error.message, { cause: error }) : error;
}
},Instead of the type assertions & Omit<...>s?
Fixes #662.
Allows
Server.elicitInput()andctx.mcpReq.elicitInput()to accept a Standard Schema/Zod object asrequestedSchema, converts it to the existing JSON Schema wire shape, and keeps JSON Schema input working unchanged.Verification:
pnpm --filter @modelcontextprotocol/server test -- jsonSchemaValidatorOverride.test.tspnpm --filter @modelcontextprotocol/core typecheckpnpm --filter @modelcontextprotocol/server typecheckpnpm --filter @modelcontextprotocol/core lintpnpm --filter @modelcontextprotocol/server lintpnpm --filter @modelcontextprotocol/server buildpnpm run typecheck:all,pnpm run build:all,pnpm run lint:allgit diff --check