Skip to content

Conversation

@petersonbill64
Copy link
Contributor

@petersonbill64 petersonbill64 commented Dec 5, 2025

Support MCP ElicitRequestParams as a union type by subclassing its two member types instead of the union itself.

Summary by CodeRabbit

  • Chores
    • Bumped project version to 0.2.6.
    • Updated MCP dependency requirement from >=1.19.0 to >=1.20.0.
    • Internal improvements to elicitation parameter handling and type safety for enhanced robustness.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Dec 5, 2025

Walkthrough

This PR bumps the project version to 0.2.6 and updates the mcp dependency to >=1.20.0. It enhances elicitation parameter handling through safer attribute access, introduces Union-based type aliases for form and URL parameters, and implements pattern-matching-based parameter transformation to propagate server_name across the elicitation flow.

Changes

Cohort / File(s) Summary
Version & Dependency Updates
pyproject.toml
Bumps project version from 0.2.5 to 0.2.6; updates mcp dependency from >=1.19.0 to >=1.20.0
Elicitation Type System
src/mcp_agent/elicitation/types.py
Introduces ElicitRequestFormParams and ElicitRequestURLParams classes extending MCP base types with optional server_name field; replaces single ElicitRequestParams with Union type alias combining both form and URL variants
Elicitation Handler
src/mcp_agent/elicitation/handler.py
Adds safe attribute access for requestedSchema using getattr() to prevent AttributeError on form-mode requests while preserving existing validation logic
Elicitation Client Session
src/mcp_agent/mcp/mcp_agent_client_session.py
Adds pattern-matching transformation of MCP elicitation parameters into agent-specific types (form/URL variants) with proper server_name propagation; imports new form and URL parameter classes
App Server Request Handling
src/mcp_agent/server/app_server.py
Replaces unified ElicitRequestParams usage with form and URL variants; adds mode-based branching logic to select appropriate parameter constructor for elicitation create requests
Workflow LLM
src/mcp_agent/workflows/llm/augmented_llm.py
Adds Tool import from mcp.types for forward reference resolution

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Pattern-matching logic in mcp_agent_client_session.py for parameter variant transformation and server_name propagation requires careful verification
  • Mode-based branching in app_server.py to ensure URL vs. Form parameter selection is correct
  • Union type definition in types.py to confirm both variants are properly defined and exported
  • Safe attribute access in handler.py to verify schema validation still works correctly for all request types

Possibly related PRs

  • Add support for elicitation #279: Modifies the same elicitation files (types.py, handler.py, mcp_agent_client_session.py), adding server_name propagation and adjusting elicitation request type handling

Suggested reviewers

  • saqadri
  • StreetLamb

Poem

🐰 A rabbit hops through param lands,
With safer types and steady hands,
Form and URL now dance in pairs,
Server names flow through the air!
Safe getattr keeps errors at bay,
Our types are stronger today!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adapting code to handle MCP 1.20.0's breaking type change regarding URL elicitation parameters.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch mcp-1-20-fix-breaking-type-change

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c67eea5 and 2cfd79b.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (6)
  • pyproject.toml (2 hunks)
  • src/mcp_agent/elicitation/handler.py (1 hunks)
  • src/mcp_agent/elicitation/types.py (1 hunks)
  • src/mcp_agent/mcp/mcp_agent_client_session.py (2 hunks)
  • src/mcp_agent/server/app_server.py (4 hunks)
  • src/mcp_agent/workflows/llm/augmented_llm.py (1 hunks)
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2025-05-27T19:10:22.911Z
Learnt from: rholinshead
Repo: lastmile-ai/mcp-agent PR: 241
File: src/mcp_agent/mcp/mcp_agent_client_session.py:174-187
Timestamp: 2025-05-27T19:10:22.911Z
Learning: In the MCP Agent codebase, all request parameter types inherit from RequestParams or NotificationParams with consistent Meta class structures, so trace context injection using the base Meta classes doesn't cause type-mismatch issues.

Applied to files:

  • src/mcp_agent/elicitation/types.py
  • src/mcp_agent/mcp/mcp_agent_client_session.py
📚 Learning: 2025-07-22T18:59:49.368Z
Learnt from: CR
Repo: lastmile-ai/mcp-agent PR: 0
File: examples/usecases/reliable_conversation/CLAUDE.md:0-0
Timestamp: 2025-07-22T18:59:49.368Z
Learning: Applies to examples/usecases/reliable_conversation/examples/reliable_conversation/src/**/*.py : Use mcp-agent's Agent abstraction for ALL LLM interactions, including quality evaluation, to ensure consistent tool access, logging, and error handling.

Applied to files:

  • src/mcp_agent/workflows/llm/augmented_llm.py
  • pyproject.toml
  • src/mcp_agent/mcp/mcp_agent_client_session.py
📚 Learning: 2025-08-28T15:07:10.015Z
Learnt from: saqadri
Repo: lastmile-ai/mcp-agent PR: 386
File: src/mcp_agent/mcp/mcp_server_registry.py:110-116
Timestamp: 2025-08-28T15:07:10.015Z
Learning: In MCP server registry methods, when client_session_factory parameters are updated to accept additional context parameters, ensure the type hints match what is actually passed (Context instance vs ServerSession) and that the default factory (MCPAgentClientSession) can handle the number of arguments being passed to avoid TypeError at runtime.

Applied to files:

  • src/mcp_agent/server/app_server.py
  • src/mcp_agent/mcp/mcp_agent_client_session.py
📚 Learning: 2025-07-22T18:59:49.368Z
Learnt from: CR
Repo: lastmile-ai/mcp-agent PR: 0
File: examples/usecases/reliable_conversation/CLAUDE.md:0-0
Timestamp: 2025-07-22T18:59:49.368Z
Learning: Applies to examples/usecases/reliable_conversation/examples/reliable_conversation/src/utils/config.py : Configuration values such as quality_threshold, max_refinement_attempts, consolidation_interval, and evaluator_model_provider must be loaded from mcp_agent.config.yaml.

Applied to files:

  • src/mcp_agent/mcp/mcp_agent_client_session.py
🧬 Code graph analysis (2)
src/mcp_agent/server/app_server.py (1)
src/mcp_agent/elicitation/types.py (2)
  • ElicitRequestFormParams (10-14)
  • ElicitRequestURLParams (17-21)
src/mcp_agent/mcp/mcp_agent_client_session.py (1)
src/mcp_agent/elicitation/types.py (2)
  • ElicitRequestFormParams (10-14)
  • ElicitRequestURLParams (17-21)
🔇 Additional comments (7)
pyproject.toml (2)

3-3: Version bump is appropriate for this patch release.

Bumping from 0.2.5 to 0.2.6 aligns with semantic versioning for bug fixes.


21-21: Verify that implementation changes handle the mcp 1.20.0 ElicitRequestParams breaking change.

Updating from >=1.19.0 to >=1.20.0 is necessary to support the breaking type change in mcp. The AI summary indicates Union-based type aliases and pattern-matching parameter transformations have been added to handle this; however, the actual implementation files are not included in this review.

Ensure that:

  • All code paths handle ElicitRequestParams as a union type (form or URL variants) rather than a single type
  • Subclassing of the union member types is correctly implemented
  • No runtime type errors occur when the new mcp version is deployed
src/mcp_agent/workflows/llm/augmented_llm.py (1)

34-34: LGTM!

The Tool import with the # noqa: F401 comment is a valid pattern for resolving forward references in Pydantic models. The comment clearly documents why this seemingly-unused import is necessary.

src/mcp_agent/elicitation/handler.py (1)

91-94: LGTM - Safe attribute access for union type compatibility.

The getattr(request, "requestedSchema", None) pattern correctly handles the case where ElicitRequestParams can now be either form or URL mode. The subsequent validation ensures the function fails gracefully with a clear error when called with URL-mode params.

src/mcp_agent/elicitation/types.py (1)

10-25: Well-designed type hierarchy for the MCP 1.20 breaking change.

The approach of subclassing both MCPElicitRequestFormParams and MCPElicitRequestURLParams to add the server_name field, then exposing a Union type alias, is a clean solution. This maintains type safety while accommodating the upstream breaking change.

src/mcp_agent/server/app_server.py (2)

1049-1061: LGTM - Mode-based elicitation parameter construction.

The branching logic correctly distinguishes between URL and form mode elicitation based on the mode parameter, with a sensible default to "form" mode. This aligns with the new union type structure introduced in the elicitation types.


1172-1178: LGTM - Auth flow correctly uses form-based elicitation.

The auth confirmation flow appropriately uses ElicitRequestFormParams with a requestedSchema derived from the AuthToken model, which is the correct type for form-based user input collection.

Comment on lines +401 to +418
# Convert MCP params to our subclass with server_name
elicitation_request: (
AgentElicitRequestFormParams | AgentElicitRequestURLParams
)
match params:
case MCPElicitRequestURLParams():
elicitation_request = AgentElicitRequestURLParams(
message=params.message,
url=params.url,
elicitationId=params.elicitationId,
server_name=server_name,
)
case MCPElicitRequestFormParams():
elicitation_request = AgentElicitRequestFormParams(
message=params.message,
requestedSchema=params.requestedSchema,
server_name=server_name,
)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# Check MCPElicitRequestFormParams definition
rg -n "class.*ElicitRequestFormParams" --type py -A 15

Repository: lastmile-ai/mcp-agent

Length of output: 1284


🏁 Script executed:

# Check AgentElicitRequestFormParams definition
rg -n "class.*AgentElicitRequestFormParams" --type py -A 15

Repository: lastmile-ai/mcp-agent

Length of output: 47


🏁 Script executed:

# Check if logger is imported in the file under review
rg -n "^import|^from" src/mcp_agent/mcp/mcp_agent_client_session.py | grep -i log

Repository: lastmile-ai/mcp-agent

Length of output: 115


🏁 Script executed:

# Check the full context of lines 401-418 to understand the match statement better
sed -n '390,430p' src/mcp_agent/mcp/mcp_agent_client_session.py

Repository: lastmile-ai/mcp-agent

Length of output: 1814


🏁 Script executed:

# Find where MCPElicitRequestFormParams and MCPElicitRequestURLParams are imported from
rg -n "from mcp" src/mcp_agent/mcp/mcp_agent_client_session.py | head -20

Repository: lastmile-ai/mcp-agent

Length of output: 769


🏁 Script executed:

# Check if there's any MCP types definition in the repo
fd "mcp.*types" --type f

Repository: lastmile-ai/mcp-agent

Length of output: 47


🏁 Script executed:

# Look for MCP library documentation or check requirements
fd "requirements\|setup\|pyproject" --type f | head -10

Repository: lastmile-ai/mcp-agent

Length of output: 47


🏁 Script executed:

# Check the local Agent types definition more thoroughly
cat -n src/mcp_agent/elicitation/types.py

Repository: lastmile-ai/mcp-agent

Length of output: 1625


🌐 Web query:

MCPElicitRequestFormParams MCPElicitRequestURLParams elicitationId field mcp types

💡 Result:

The elicitationId field is a string (typically a UUID). See the MCP elicitation spec and SDK examples showing elicitationId passed as a string/UUID in URL/form elicitation requests. [1][2]

Sources:
[1] Model Context Protocol — Elicitation (spec).
[2] modelcontextprotocol python/TypeScript SDK examples (elicit URL example using elicitationId as a UUID string).


🏁 Script executed:

# Search for any usage examples of these MCP types in tests or elsewhere
rg -n "MCPElicitRequestFormParams|MCPElicitRequestURLParams" --type py -B 2 -A 5

Repository: lastmile-ai/mcp-agent

Length of output: 3683


🏁 Script executed:

# Check if there are any tests that show how these params are used
fd "test.*\.py" --type f | xargs rg -l "Elicit" 2>/dev/null | head -5

Repository: lastmile-ai/mcp-agent

Length of output: 110


🏁 Script executed:

# Check the test file to see how elicitation is tested
cat -n tests/human_input/test_elicitation_handler.py | head -80

Repository: lastmile-ai/mcp-agent

Length of output: 3758


🏁 Script executed:

# Check if AgentElicitRequestFormParams (or its parent) has elicitationId field
rg -n "class.*AgentElicitRequest" src/ -A 10

Repository: lastmile-ai/mcp-agent

Length of output: 47


🏁 Script executed:

# Check the full match statement context and what comes after it
sed -n '400,430p' src/mcp_agent/mcp/mcp_agent_client_session.py

Repository: lastmile-ai/mcp-agent

Length of output: 1388


🏁 Script executed:

# Search more broadly for Agent* classes related to elicitation
rg -n "AgentElicit" src/ --type py -B 1 -A 5

Repository: lastmile-ai/mcp-agent

Length of output: 2450


🏁 Script executed:

# Check what happens after the match statement - does it fail if no case matches?
sed -n '413,435p' src/mcp_agent/mcp/mcp_agent_client_session.py

Repository: lastmile-ai/mcp-agent

Length of output: 1016


🏁 Script executed:

# Look for the import of AgentElicitRequestFormParams and AgentElicitRequestURLParams
rg -n "from.*import.*AgentElicit" src/mcp_agent/mcp/mcp_agent_client_session.py -B 2 -A 2

Repository: lastmile-ai/mcp-agent

Length of output: 47


Add missing elicitationId field to form params conversion.

The URL params conversion includes elicitationId (line 410), but the form params conversion omits it. According to the MCP elicitation spec, both MCPElicitRequestFormParams and MCPElicitRequestURLParams contain an elicitationId field that must be preserved when converting to the agent subclass.

                 case MCPElicitRequestFormParams():
                     elicitation_request = AgentElicitRequestFormParams(
                         message=params.message,
                         requestedSchema=params.requestedSchema,
+                        elicitationId=params.elicitationId,
                         server_name=server_name,
                     )
🤖 Prompt for AI Agents
In src/mcp_agent/mcp/mcp_agent_client_session.py around lines 401 to 418, the
form-params branch building AgentElicitRequestFormParams omits the elicitationId
field; add elicitationId=params.elicitationId to the
AgentElicitRequestFormParams constructor so the field is preserved when
converting MCPElicitRequestFormParams to the agent subclass, keeping parameter
naming consistent with the URL branch.

Copy link
Collaborator

@saqadri saqadri left a comment

Choose a reason for hiding this comment

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

Looks correct, thanks for fixing. Let's ship and fix forward from here

SamplingMessage,
TextContent,
PromptMessage,
Tool, # noqa: F401 - Required to resolve forward reference in CreateMessageRequestParams
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't follow this one

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I get

pydantic.errors.PydanticUserError: `RequestParams` is not fully defined; you should define `Tool`, then call `RequestParams.model_rebuild()`

when running the elicitation example without this

req = ElicitRequest(
method="elicitation/create",
params=ElicitRequestParams(
params=ElicitRequestFormParams(
Copy link
Collaborator

Choose a reason for hiding this comment

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

@romanvanderkrogt should the auth flow now use url based elicitation?

@petersonbill64 petersonbill64 merged commit 070e7e9 into main Dec 5, 2025
7 of 8 checks passed
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.

3 participants