Repository navigation
[Bug] check_capability does not validate elicitation sub-capabilities (form/url) #2965
Copy link
Copy link
Open
Labels
P2Moderate issues affecting some users, edge cases, potentially valuable featureModerate issues affecting some users, edge cases, potentially valuable featurebugSomething isn't workingSomething isn't workingneeds confirmationNeeds confirmation that the PR is actually required or needed.Needs confirmation that the PR is actually required or needed.v2Affects the v2 line (2.x on main)Affects the v2 line (2.x on main)
Description
Summary
Connection.check_capability() returns True when a client has URL-mode elicitation but the caller checks for form-mode elicitation — the sub-capability (ElicitationCapability.form / .url) is never inspected.
Root cause
In src/mcp/server/connection.py:340-341:
if capability.elicitation is not None and have.elicitation is None:
return FalseThis only returns False when the client has no elicitation at all. It does not check individual sub-capabilities (form / url). Compare with sampling, which correctly checks sub-capabilities:
if capability.sampling is not None:
if have.sampling is None:
return False
if capability.sampling.context is not None and have.sampling.context is None:
return False
if capability.sampling.tools is not None and have.sampling.tools is None:
return FalseReproduction
# Client supports URL elicitation only
have = ClientCapabilities(elicitation=ElicitationCapability(url=UrlElicitationCapability()))
# Check for form elicitation — should be False (client does not have form)
want = ClientCapabilities(elicitation=ElicitationCapability(form=FormElicitationCapability()))
Connection.from_envelope("2025-11-25", client_info, have).check_capability(want) # Returns True (BUG)Impact
check_capabilityis public API (viaServerSession.check_client_capability)- Currently no production callers use elicitation sub-capability checks — low immediate impact
- But once someone relies on it (e.g., checking if the client supports form elicitation before calling
elicit_form), it will return wrong results
Additional gaps (lower priority)
extensions—ClientCapabilities.extensionsis not checked at alltasks—ClientCapabilities.tasksand sub-capabilities entirely unhandled
Proposed fix
Add form / url sub-capability checks, matching the sampling pattern:
if capability.elicitation is not None:
if have.elicitation is None:
return False
if capability.elicitation.form is not None and have.elicitation.form is None:
return False
if capability.elicitation.url is not None and have.elicitation.url is None:
return FalseAI assistance: Bug discovered and analyzed with AI assistance (opencode).
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
P2Moderate issues affecting some users, edge cases, potentially valuable featureModerate issues affecting some users, edge cases, potentially valuable featurebugSomething isn't workingSomething isn't workingneeds confirmationNeeds confirmation that the PR is actually required or needed.Needs confirmation that the PR is actually required or needed.v2Affects the v2 line (2.x on main)Affects the v2 line (2.x on main)
Activity
syf2211 commentedon Jun 26, 2026
Rodrigo-Palma commentedon Jul 3, 2026
I ran into this as well and opened #3061 with a fix. It mirrors the existing
samplingsub-capability handling forelicitation.form/elicitation.url: when a specific mode is requested, the client must declare that mode; a bare elicitation request is still satisfied by any elicitation support.The PR extends the existing
test_check_capability_per_field_branchesparametrization with the two bug cases (URL-only client vs. form request, and form-only vs. URL) plus the positive/bare cases — the bug cases fail onmainand pass with the change.pytest,pyright, andruffare all green.I scoped it to elicitation only:
extensionsalready appears handled onmain(SEP-2133), and I lefttasksout to keep the PR small — happy to follow up separately. Glad to be assigned if this looks good.(AI-assisted analysis and drafting; the change is reviewed and understood by me.)