feat!: hard-fail elicitation when client cannot prompt for confirmation#1208
Open
manjunathshiva wants to merge 1 commit into
Open
feat!: hard-fail elicitation when client cannot prompt for confirmation#1208manjunathshiva wants to merge 1 commit into
manjunathshiva wants to merge 1 commit into
Conversation
Per OWASP MCP Top 10 (2025) item MCP06 - Intent Flow Subversion.
Tools listed in `confirmationRequiredTools` no longer execute silently
against MCP clients that don't advertise the `elicitation` capability;
they refuse with a structured error that names the missing capability.
Before this change, Elicitation.requestConfirmation() returned a bare
`true` whenever the client didn't support elicitation, which meant a
confirmation-gated operation (drop-database, atlas-create-db-user,
etc.) would proceed against an older client without the user ever
seeing a confirmation prompt. The user never had the chance to
consent, so silently proceeding is a policy violation: no consent, no
execute.
Changes:
src/elicitation.ts
- requestConfirmation() return type changes from `Promise<boolean>` to
a tagged union ConfirmationResult: `{ ok: true } | { ok: false;
reason: 'declined' | 'no-elicitation-support' }`. The new type is
exported so callers can distinguish "user said no" from "client
cannot ask". Both block execution; the two cases want different
error messages and different audit-log severities.
src/tools/tool.ts
- ToolBase.verifyConfirmed() now returns ConfirmationResult.
- ToolBase.invoke() inspects the reason. For 'no-elicitation-support'
it logs a warning via the new LogId.toolBlockedNoElicitation and
returns an actionable error telling the user/operator to either use
an elicitation-capable client or remove the tool from
confirmationRequiredTools. For 'declined' it preserves the previous
user-decline message and debug-level log.
src/common/logging/loggingDefinitions.ts
- New LogId.toolBlockedNoElicitation (1_003_005) for audit-trail
visibility into MCP06 refusals.
src/lib.ts and src/web.ts
- ConfirmationResult is now exported from both entry points so
embedders that wrap requestConfirmation see the same type the
server uses.
Tests:
- tests/unit/elicitation.test.ts: every assertion against
requestConfirmation now compares against the tagged shape. New test
explicitly verifies the OWASP MCP06 fail-closed behaviour.
- tests/unit/toolBase.test.ts: verifyConfirmed return-type updated;
two new tests cover the 'declined' and 'no-elicitation-support'
propagation paths.
- tests/unit/toolContext.test.ts and the streams unit-test mocks
updated to resolve `{ ok: true }` instead of bare booleans.
api-extractor reports regenerated.
BREAKING CHANGE: Elicitation.requestConfirmation() return type changes
from Promise<boolean> to Promise<ConfirmationResult>. Downstream code
that awaited the old boolean must switch to inspecting `.ok` (and
optionally `.reason`). Likewise ToolBase.verifyConfirmed() now returns
ConfirmationResult.
Operationally: MCP clients that DON'T advertise the `elicitation`
capability will see refusals when invoking the eight tools currently
in `confirmationRequiredTools` (drop-database, drop-collection,
delete-many, drop-index, atlas-create-access-list,
atlas-create-db-user, atlas-streams-manage,
atlas-streams-teardown). Clients that DO advertise the capability are
unaffected. The error message points operators at the resolution
paths (upgrade the client, or remove the tool from the list).
Collaborator
|
LGTM |
Collaborator
|
tests are failing, make sure to adjust CI |
nirinchev
requested changes
May 27, 2026
nirinchev
left a comment
Collaborator
There was a problem hiding this comment.
I'm not convinced we want to go that route. While I understand the intention, it will be a breaking behavior for many users with clients that don't support elicitation. We'll have to discuss that internally to decide whether the benefits outweigh the disruptiveness.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Per OWASP MCP Top 10 (2025) item MCP06 - Intent Flow Subversion. Tools listed in
confirmationRequiredToolsno longer execute silently against MCP clients that don't advertise theelicitationcapability; they refuse with a structured error that names the missing capability.Before this change, Elicitation.requestConfirmation() returned a bare
truewhenever the client didn't support elicitation, which meant a confirmation-gated operation (drop-database, atlas-create-db-user, etc.) would proceed against an older client without the user ever seeing a confirmation prompt. The user never had the chance to consent, so silently proceeding is a policy violation: no consent, no execute.Changes:
src/elicitation.ts
Promise<boolean>to a tagged union ConfirmationResult:{ ok: true } | { ok: false; reason: 'declined' | 'no-elicitation-support' }. The new type is exported so callers can distinguish "user said no" from "client cannot ask". Both block execution; the two cases want different error messages and different audit-log severities.src/tools/tool.ts
src/common/logging/loggingDefinitions.ts
src/lib.ts and src/web.ts
Tests:
{ ok: true }instead of bare booleans.api-extractor reports regenerated.
BREAKING CHANGE: Elicitation.requestConfirmation() return type changes from Promise to Promise. Downstream code that awaited the old boolean must switch to inspecting
.ok(and optionally.reason). Likewise ToolBase.verifyConfirmed() now returns ConfirmationResult.Operationally: MCP clients that DON'T advertise the
elicitationcapability will see refusals when invoking the eight tools currently inconfirmationRequiredTools(drop-database, drop-collection, delete-many, drop-index, atlas-create-access-list, atlas-create-db-user, atlas-streams-manage,atlas-streams-teardown). Clients that DO advertise the capability are unaffected. The error message points operators at the resolution paths (upgrade the client, or remove the tool from the list).
Proposed changes
Checklist