ADR-017: Elicitation Passthrough ImplementationΒΆ
- Status: Accepted
- Date: 2025-10-26
- Deciders: Mihai Criveti
- Technical Story: spec/status.md item #27
ContextΒΆ
The Model Context Protocol (MCP) specification version 2025-06-18 introduced elicitation as a new feature for interactive user input workflows. Elicitation allows MCP servers to request structured information from users through the client during tool execution or other operations.
MCP Elicitation OverviewΒΆ
Flow Pattern: Server β Client (reverse request pattern)
sequenceDiagram
participant Server as MCP Server
participant Gateway as MCP Gateway
participant Client as Client (Claude Desktop)
participant User
Server->>Gateway: elicitation/create request
Gateway->>Client: Forward elicitation/create
Client->>User: Display UI (form/dialog)
User->>Client: Provide input (accept/decline/cancel)
Client->>Gateway: Return ElicitResult
Gateway->>Server: Forward result
Server->>Server: Continue processing with user input Key Characteristics: - Newly introduced: First appeared in MCP 2025-06-18, design may evolve - Optional capability: Clients must advertise {"elicitation": {}} during initialization - Nested execution: Elicitation can occur inside tool/resource/prompt operations - Three-action model: Users can accept (with data), decline, or cancel - Structured schemas: Requests include JSON Schema (restricted to primitive types)
Gateway Architectural ChallengeΒΆ
The MCP Gateway operates as both: 1. Server to downstream clients (Claude Desktop, API consumers) 2. Client to upstream servers (MCP servers, federated gateways)
This dual role creates complexity for elicitation: - Upstream servers initiate elicitation requests - Gateway must forward to appropriate downstream clients - Responses must be routed back to the original requester - Session state must track pending elicitations
Current StateΒΆ
File: mcpgateway/main.py:3622-3623
Problem: Returns empty dict instead of proper handling, breaking MCP spec compliance.
DecisionΒΆ
Implement full passthrough elicitation support with the following architecture:
1. Bidirectional Proxy PatternΒΆ
# Server-to-Client flow (elicitation/create)
Upstream Server β Gateway β Downstream Client β User
User β Client β Gateway β Server
# Request tracking
ElicitationService tracks:
- request_id β (upstream_session, downstream_session, timeout)
- Maps responses back to original requestor
2. Component ArchitectureΒΆ
New Service: mcpgateway/services/elicitation_service.py - Track active elicitation requests - Map request IDs between upstream/downstream sessions - Handle timeouts and cleanup - Validate schemas per MCP spec
Updated Components: - mcpgateway/cache/session_registry.py - Track client elicitation capability - mcpgateway/models.py - Add Pydantic models for elicitation types - mcpgateway/main.py - Implement elicitation/create handler
3. Configuration StrategyΒΆ
# .env.example / config.py
MCPGATEWAY_ELICITATION_ENABLED=true # Master switch
MCPGATEWAY_ELICITATION_TIMEOUT=60 # Default timeout (seconds)
MCPGATEWAY_ELICITATION_MAX_CONCURRENT=100 # Max concurrent requests
4. Error HandlingΒΆ
# Scenarios handled:
1. Client doesn't support elicitation β Error -32601 (Capability not available)
2. No active downstream clients β Error -32000 (No capable clients connected)
3. Timeout waiting for response β Error -32000 (Elicitation timeout)
4. Invalid schema β Error -32602 (Invalid params)
5. Gateway elicitation disabled β Error -32601 (Feature disabled)
5. Security ConsiderationsΒΆ
Per MCP spec security requirements: - No sensitive data: Validate schemas don't request passwords, API keys, etc. - Rate limiting: Enforce max concurrent elicitations per session - Timeout enforcement: Prevent indefinite blocking - Audit logging: Log all elicitation requests and responses (sanitized)
Implementation PlanΒΆ
Phase 1: Foundation (Priority: High)ΒΆ
-
Add Pydantic Models (
mcpgateway/models.py) -
Create ElicitationService (
mcpgateway/services/elicitation_service.py) - Request tracking data structure
- Timeout management
- Response routing logic
-
Schema validation (primitive types only)
-
Update SessionRegistry (
mcpgateway/cache/session_registry.py) - Track client
elicitationcapability from initialization - Store capability per session
- Provide lookup for capable clients
Phase 2: Request Handling (Priority: High)ΒΆ
-
Implement Handler (
mcpgateway/main.py) -
Add Configuration (
.env.example,config.py) - Feature flags
- Timeout settings
- Concurrency limits
Phase 3: Testing & Documentation (Priority: Medium)ΒΆ
- Unit Tests
- ElicitationService request tracking
- Schema validation (primitive types only)
- Timeout handling
-
Error scenarios
-
Integration Tests
- End-to-end elicitation flow
- Multiple concurrent requests
- Client capability negotiation
-
Response routing
-
Update Documentation
spec/status.md- Mark item #27 as completedREADME.md- Document elicitation configuration- API docs - Document elicitation endpoints
Estimated ImplementationΒΆ
- Lines of Code: ~300-400 (service + models + tests)
- Files Modified: 6-8 files
- Time Estimate: 4-6 hours implementation + 2-3 hours testing
Alternatives ConsideredΒΆ
Alternative 1: Stub Implementation (Return Error)ΒΆ
Decision: β Rejected
Rationale: - β Pro: Simplest implementation (5 lines of code) - β Pro: Honest about lack of support - β Con: Breaks MCP spec compliance (feature is in 2025-06-18 spec) - β Con: Limits gateway usability with elicitation-enabled servers - β Con: Future implementation requires complete rewrite
Alternative 2: Gateway-Initiated Elicitation OnlyΒΆ
Decision: β Rejected
Implement elicitation for gateway's own use (e.g., configuration wizards) but not passthrough.
Rationale: - β Pro: Simpler than passthrough (no session tracking) - β Pro: Useful for gateway admin UI workflows - β Con: Doesn't solve spec compliance for upstream servers - β Con: Limited real-world use cases for gateway-initiated elicitation - β Con: Still requires full implementation later for spec compliance
Alternative 3: Async Queue-Based ArchitectureΒΆ
Decision: β Rejected
Use message queue (Redis, RabbitMQ) for elicitation request routing.
Rationale: - β Pro: Better scalability for high-volume scenarios - β Pro: Natural timeout/retry handling - β Con: Adds external dependency complexity - β Con: Overkill for typical elicitation volumes (low frequency, human-in-loop) - β Con: More difficult to debug and troubleshoot - β Con: Increases deployment complexity
ConsequencesΒΆ
Positive β ΒΆ
- MCP 2025-06-18 Compliance: Gateway fully supports latest spec
- Interactive Workflows: Enables rich user interaction patterns from upstream servers
- Future-Proof: Ready for elicitation adoption as feature matures
- Federated Support: Multi-tier gateway deployments can pass elicitations through
- Configuration Flexibility: Can disable if not needed, minimal overhead when disabled
- Security First: Validates schemas, enforces timeouts, prevents abuse
Negative βΒΆ
- Session Complexity: Adds request/response tracking across sessions
- Memory Overhead: Must track pending elicitations (mitigated by timeout/limits)
- Testing Complexity: Requires end-to-end test infrastructure
- Error Handling: Multiple failure modes require careful handling
- Feature Maturity: MCP spec notes "design may evolve" - risk of breaking changes
Neutral πΒΆ
- Adoption Uncertainty: Unknown how many servers will use elicitation
- Performance Impact: Minimal (elicitations are human-speed, not hot path)
- Maintenance: New service requires ongoing maintenance as spec evolves
Risks and MitigationsΒΆ
Risk 1: Spec EvolutionΒΆ
Risk: MCP spec notes elicitation design "may evolve in future versions"
Mitigation: - β Implement behind feature flag for easy disabling - β Comprehensive unit tests allow rapid updates - β Schema validation centralizes spec-dependent logic - β Monitor MCP spec changes and update promptly
Risk 2: Session Tracking BugsΒΆ
Risk: Request/response routing errors could cause hangs or wrong responses
Mitigation: - β Aggressive timeouts (60s default, configurable) - β Comprehensive error handling and logging - β Request ID validation prevents mis-routing - β Automatic cleanup of expired requests
Risk 3: Client Capability DetectionΒΆ
Risk: Incorrectly routing to non-capable clients
Mitigation: - β Validate client capabilities during initialization - β Store capability per session - β Return clear error if no capable clients available - β Log capability negotiation for debugging
Success MetricsΒΆ
- Functional:
- β All elicitation spec requirements implemented
- β 100% test coverage for ElicitationService
-
β Integration tests pass for all scenarios
-
Performance:
- β Elicitation overhead <10ms (excluding human response time)
- β No memory leaks from pending requests
-
β Graceful handling of 100+ concurrent elicitations
-
Operations:
- β Clear error messages for all failure modes
- β Comprehensive logging for debugging
- β Configuration validation on startup
- β Metrics exposed for monitoring
ReferencesΒΆ
- MCP Specification:
spec/modelcontextprotocol/docs/specification/2025-06-18/client/elicitation.mdx - FastMCP Implementation:
.venv/lib/python3.12/site-packages/mcp/server/elicitation.py - Status Tracking:
spec/status.mditem #27 - MCP Types Reference:
.venv/lib/python3.12/site-packages/mcp/types.pylines 1277-1311
Decision Approved By: Mihai Criveti Implementation Tracked In: This ADR becomes the implementation specification for elicitation support.