Skip to content

Conversation

@mcollina
Copy link
Member

No description provided.

mcollina and others added 5 commits September 11, 2025 18:12
Implements Server-Sent Events (SSE) streaming for tool results that return async iterators, enabling real-time streaming of tool outputs through POST requests.

Key Features:
- Detects async iterators using Symbol.asyncIterator
- Automatic response type selection (JSON vs SSE)
- Streams each yielded chunk as separate SSE event
- Maintains backward compatibility with immediate JSON responses
- Robust error handling during streaming
- Per-session event ID tracking for SSE events

Files Added:
- test/async-iterator-streaming.test.ts: Comprehensive test suite (5 tests)
- examples/streaming-demo.ts: Working demonstration server

Files Modified:
- src/types.ts: Extended types for async generator support
- src/handlers.ts: Added streaming response detection and interface
- src/routes/mcp.ts: Implemented SSE streaming logic for POST responses

Testing:
- All 281 tests passing including 5 new streaming-specific tests
- Tests cover immediate responses, streaming, error handling, and event sequencing
- Demo server with curl examples for manual verification

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
Fixes critical MCP specification compliance issue where event IDs were assigned per-session instead of per-stream, breaking Last-Event-ID resumability.

Key Changes:
- Updated SessionStore interface to support per-stream tracking with StreamMetadata
- Added stream ID generation and management for each SSE connection
- Implemented per-stream event ID sequences starting from 1
- Modified message storage to organize by streamId, not just sessionId
- Updated replay logic to work with per-stream cursors
- Maintained backwards compatibility with legacy session-level methods

Per MCP Transport Specification:
- Line 169: "event IDs should be assigned by servers on a per-stream basis"
- Line 143: "client MAY remain connected to multiple SSE streams simultaneously"
- Line 145: "server MUST send each message on only one of the connected streams"

Files Modified:
- src/stores/session-store.ts: Added per-stream interface methods
- src/stores/memory-session-store.ts: Implemented per-stream storage
- src/stores/redis-session-store.ts: Added Redis per-stream support
- src/routes/mcp.ts: Per-stream SSE implementation with stream IDs
- test/per-stream-event-ids.test.ts: Test suite for per-stream compliance

Testing:
- 284/286 tests passing (2 Redis integration test failures to address)
- New per-stream test suite covering event ID architecture
- Fixed async iterator streaming test expectations
- Updated all session creation to include streams Map

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
Updates Redis integration tests to work with the new per-stream event ID architecture while maintaining backward compatibility.

Key Changes:
- Modified sendSSEToStreams to detect broadcast notifications and elicitation requests
- Added isBroadcast logic to use legacy session-level storage for notifications
- Updated sendSSEToStreamsLegacy to store messages in session history for backward compatibility
- Fixed tests expecting session-level message storage for broadcast/elicitation messages

Per-stream messages use per-stream storage, while broadcast notifications and elicitation requests use session-level storage to maintain compatibility with existing tests and expected behavior.

Testing:
- All 286 tests now passing
- Redis integration tests (7/7) passing
- Broadcast notifications properly stored in session history
- Elicitation requests properly stored in session history

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
The broadcast system is a core feature, not legacy. Updates terminology throughout:
- sendSSEToStreamsLegacy → sendSSEToStreamsBroadcast
- 'Legacy' comments → 'Broadcast' comments
- Clarifies that broadcast messages are session-wide by design
- Maintains same functionality with clearer naming

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
Adds detailed documentation for the new async iterator streaming feature:

Key additions:
- Async Iterator Streaming section with complete examples
- Basic streaming tool implementation patterns
- Advanced streaming examples (file processing, error handling)
- Client usage examples with curl commands
- Streaming response format explanation
- Key features and benefits overview

Documentation covers:
- Automatic async iterator detection
- Real-time SSE streaming capabilities
- Error handling during streaming
- Backward compatibility guarantees
- MCP specification compliance
- Performance and resumability features

Updated Features section to highlight:
- Async Iterator Streaming as a key feature
- Per-Stream Event IDs for MCP compliance
- Real-time streaming capabilities

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
@mcollina mcollina marked this pull request as ready for review September 11, 2025 17:09
Signed-off-by: Matteo Collina <[email protected]>
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.

2 participants