feat(tools): Elicitation pass-through implementation with session routing and observability#4091
Open
bogdanmariusc10 wants to merge 5 commits intomainfrom
Open
feat(tools): Elicitation pass-through implementation with session routing and observability#4091bogdanmariusc10 wants to merge 5 commits intomainfrom
bogdanmariusc10 wants to merge 5 commits intomainfrom
Conversation
…outing and observability - Add tool_call_registry for mapping tool calls to originating sessions - Implement elicitation callback in tool_service for SSE and Streamable HTTP - Add session capability enforcement before forwarding elicitation requests - Integrate structured logging for elicitation lifecycle events - Add Prometheus metrics (requests, completions, timeouts, duration) - Add comprehensive integration tests (13 tests covering all user stories) - Initialize tool_call_registry in application lifespan - Fix linting issues (trailing whitespace, blank lines) Closes #1985 Signed-off-by: Bogdan-Marius-Catanus <bogdan-marius.catanus@ibm.com>
50 tasks
- Fixed import grouping in metrics.py (moved Histogram to top-level imports) - Fixed malformed docstring in tool_service.py capability_error_callback - Used params.message in logging to satisfy unused argument check - Added comprehensive test coverage for elicitation callbacks - Added unit tests for ToolCallRegistry to improve coverage - Tests cover error paths, timeout handling, and edge cases Signed-off-by: Bogdan-Marius-Catanus <bogdan-marius.catanus@ibm.com>
Collaborator
|
@bogdanmariusc10 - thanks for the contribution! |
Signed-off-by: Bogdan-Marius-Catanus <bogdan-marius.catanus@ibm.com>
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.
🔗 Related Issue
Closes #1985
📝 Summary
This PR implements complete MCP elicitation pass-through functionality per the MCP 2025-06-18 specification, enabling MCP servers to request structured user input during tool execution with proper session routing in multi-user deployments.
Key capabilities:
elicitation/createrequests during tool execution🏷️ Type of Change
🧪 Verification
make lintmake testmake coverageTest Results:
✅ Checklist
make black isort pre-commit)📓 Implementation Details
Architecture
sequenceDiagram participant Client as MCP Client (User A) participant Gateway participant Registry as ToolCallRegistry participant Server as MCP Server Client->>Gateway: tools/call "delete_files" Gateway->>Registry: Store mapping: call-456 -> sess-123 Gateway->>Server: Execute tool Server->>Gateway: elicitation/create Gateway->>Registry: Lookup session for call-456 Gateway->>Client: Forward to sess-123 only Client->>Gateway: Elicitation response (action: "accept") Gateway->>Server: ElicitResult Server->>Gateway: Tool result Gateway->>Client: Tool responseNew Components
ToolCallRegistry (
mcpgateway/cache/tool_call_registry.py)tool_call_id → downstream_session_idfor session correlationElicitation Callback (
mcpgateway/services/tool_service.py)_create_elicitation_callback_for_tool_invocation()ElicitationServiceto forward requests to correct clientCapability Enforcement
session.capabilities.elicitationbefore forwarding-32601error if client lacks capabilityStructured Logging
created,delivered,completed,timeout,errorPrometheus Metrics
elicitation_requests_total- Counterelicitation_completed_total- Counter (by action)elicitation_timeout_total- Counterelicitation_duration_seconds- HistogramModified Files
mcpgateway/cache/tool_call_registry.pytests/integration/test_elicitation_passthrough.pytests/integration/test_elicitation_callback_coverage.pytests/unit/test_tool_call_registry_coverage.pymcpgateway/services/tool_service.pymcpgateway/services/elicitation_service.pymcpgateway/services/metrics.pymcpgateway/transports/streamablehttp_transport.pymcpgateway/main.pyConfiguration
Existing settings in
mcpgateway/config.py(no new env vars required):Test Coverage
13 comprehensive integration tests covering:
Test scenarios:
Design Decisions
Session Mapping Strategy: Used dedicated
ToolCallRegistryinstead of extendingSessionRegistryto maintain separation of concerns and avoid circular dependencies.Callback Integration: Implemented callback at tool invocation time (not transport layer) to ensure proper context and correlation regardless of transport type.
Fail-Closed Security: If session mapping is missing or capability check fails, return clear error to server rather than attempting broadcast or fallback.
Structured Logging: Emit events at key lifecycle points (created, delivered, completed, timeout, error) with full context for debugging and audit trails.
Metrics Granularity: Track both success/failure counts and latency distribution to enable SLO monitoring and performance analysis.
📚 References