…uth compliance
## Critical Transport Architecture Fix
This commit resolves two fundamental issues that prevented MCP HTTP transport
from working correctly with traditional PHP servers (PHP-FPM, Apache) while
maintaining compatibility with long-running processes (ReactPHP).
### 🔧 Problem 1: Client Registration Lost Between Requests
**Root Cause:**
Each HTTP request in PHP-FPM/Apache runs in a separate PHP process, causing:
- SSE stream (GET /sse) creates LaravelHttpTransport instance #1
- POST requests (/message) create LaravelHttpTransport instance #2
- Client registered in instance #1 is not available in instance #2
- Result: "Client not actively managed by this transport" errors
**Solution:**
Auto-registration in `LaravelHttpTransport::sendToClientAsync()`:
- Automatically emit `client_connected` event for unknown clients
- Ensures clients are active before processing messages
- Maintains backward compatibility with ReactPHP (no-op for already active clients)
### 🔧 Problem 2: OAuth Standard Compliance
**Root Cause:**
Original package used non-standard parameter naming that violates OAuth spec:
- Used: `clientId` (camelCase)
- OAuth Standard: `client_id` (snake_case)
- Real MCP clients (Claude Desktop) send `client_id` parameter
**Solution:**
- Updated SSE endpoint to accept `client_id` query parameter
- Consistent `client_id` usage in all log messages
- Maintains fallback to session ID if no `client_id` provided
### 🔧 Problem 3: Service Provider Architecture
**Root Cause:**
Multiple controller instantiations called `server->listen()` repeatedly, causing:
- Event handlers registered multiple times
- Transport state inconsistencies
- Memory leaks and performance issues
**Solution:**
- Moved `server->listen()` to McpServiceProvider singleton registration
- Removed redundant `server->listen()` calls from controller constructor
- Proper logger injection in service provider
## 🧪 Tested Scenarios
✅ **PHP-FPM/Apache (Separate Processes)**
- Each request gets clean transport instance
- Auto-registration ensures client connectivity
- No shared state issues
✅ **ReactPHP (Long-Running Process)**
- Existing clients remain active
- Auto-registration is no-op for active clients
- No performance impact
✅ **Claude Desktop Integration**
- Recognizes all MCP tools correctly
- Proper `client_id` parameter handling
- SSE stream maintains connection
## 🔍 Technical Details
**Modified Files:**
- `src/Transports/LaravelHttpTransport.php`: Auto-registration logic
- `src/Http/Controllers/McpController.php`: OAuth compliance + service provider cleanup
- `src/McpServiceProvider.php`: Centralized transport initialization
**Key Changes:**
1. Auto-registration in `sendToClientAsync()` when client not found
2. SSE endpoint accepts `client_id` query parameter
3. Service provider handles transport listening lifecycle
4. Consistent `client_id` logging throughout
## 🚀 Impact
**Before:** MCP HTTP transport only worked with ReactPHP
**After:** Works with all PHP server configurations
**Deployment:** Zero breaking changes - existing code continues to work
**Performance:** Minimal overhead (~1 isset() check per message)
This fix enables MCP HTTP transport to work reliably in production PHP
environments while maintaining the existing API and functionality.
Fixes issues with:
- Traditional PHP-FPM deployments
- Apache mod_php configurations
- Docker containers with nginx+php-fpm
- Shared hosting environments
- Any setup where each HTTP request runs in separate PHP process
Co-authored-by: Claude (Anthropic) <[email protected]>