-
Notifications
You must be signed in to change notification settings - Fork 434
Open
Labels
Milestone
Description
Summary
Rewrite the wrapper module in Rust - the HTTP client bridge that forwards stdio JSON-RPC requests to remote HTTP endpoints, parsing streaming responses (SSE, NDJSON) with incremental UTF-8 decoding.
Current Implementation
File: mcpgateway/wrapper.py
The wrapper module handles:
- HTTP client requests to remote MCP endpoints
- Streaming response parsing (SSE, NDJSON)
- Incremental UTF-8 decoding
- JSON-RPC message forwarding
Rust Benefits
| Aspect | Python | Rust |
|---|---|---|
| Stream parsing | Per-chunk overhead | Native zero-copy |
| UTF-8 decoding | Python string alloc | In-place with bytes |
| Message roundtrip | ~5ms overhead | ~0.5ms overhead |
| Buffer management | O(n²) string concat | O(1) with BytesMut |
Key Improvements
- Native stream parsing with
nom/byteseliminates per-chunk Python overhead - Zero-copy buffer management using
BytesMutinstead of Python string concatenation - Significant savings per message roundtrip - reduced latency for every MCP call
- Efficient incremental UTF-8 handling without Python string allocations
Proposed Architecture
┌─────────────────────────────────────────────────────────┐
│ Rust Core (PyO3) │
├─────────────────────────────────────────────────────────┤
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │
│ │ HTTP Client │ │ SSE Parser │ │ NDJSON Parser │ │
│ │ (reqwest) │ │ (nom/bytes) │ │ (serde_json) │ │
│ └─────────────┘ └─────────────┘ └─────────────────┘ │
├─────────────────────────────────────────────────────────┤
│ Python Interface │
│ (async def forward_request(...) -> Response) │
└─────────────────────────────────────────────────────────┘
Current Performance Issues
From todo/newperf/optimize-stream-parser-buffers.md:
# Current O(n²) pattern in wrapper.py
buffer = ""
async for chunk in resp.aiter_bytes():
buffer += text # O(n) - creates new string!
buffer = buffer[nl_idx + 1:] # O(n) - creates new string!Rust eliminates this entirely with BytesMut::split_to().
Implementation Approach
Phase 1: Stream Parsers
- Implement SSE parser with
nomcombinators - Implement NDJSON parser with streaming
serde_json - Create
BytesMut-based buffer management
Phase 2: HTTP Client
- Build async HTTP client with
reqwest - Add connection pooling and keep-alive
- Implement streaming response handling
Phase 3: PyO3 Integration
- Expose as async Python module
- Return Python async iterators for streaming
- Maintain httpx-compatible interface
Crates to Use
reqwest- HTTP clienttokio- async runtimebytes- buffer managementnomorwinnow- stream parsingserde_json- JSON handlingpyo3+pyo3-asyncio- Python bindings
Acceptance Criteria
- Stream parsing is O(n) not O(n²)
- Memory usage bounded regardless of response size
- Message roundtrip latency < 1ms overhead
- Compatible with existing wrapper API
- Passes existing wrapper tests
- Supports SSE, NDJSON, and chunked responses