UNPKG

mcp-http-bridge

Version:

Generic bridge client for connecting MCP clients to remote MCP servers via HTTP supporting session based environment variables

526 lines (422 loc) • 15.9 kB
# MCP HTTP Bridge A generic bridge client that enables [Cursor](https://cursor.sh) to connect to remote MCP (Model Context Protocol) servers via HTTP with OAuth authentication support. ## What It Does This bridge converts Cursor's stdio-based MCP interface to HTTP requests, allowing you to: - 🌐 Connect Cursor to **remote MCP servers** deployed anywhere - šŸ” **OAuth authentication** with automatic browser-based login flow - šŸ”§ Pass **environment variables** as HTTP headers automatically - šŸŽÆ Control **exactly which variables** get passed to remote servers - šŸ”’ Keep **sensitive configuration** secure with proper filtering - šŸ“” Support **Server-Sent Events (SSE)** for streaming responses - šŸ› **Debug logging** for troubleshooting connections - šŸŽ« **Session management** for stateful server interactions ## Installation ### Option 1: NPX (Recommended - No Installation Required) Use `npx` to run the latest version automatically without installing: ```json { "mcpServers": { "remote-server": { "command": "npx", "args": ["mcp-http-bridge@latest"], "env": { "MCP_SERVER_URL": "https://your-mcp-server.com/mcp", "MCP_PASS_VARS": "API_KEY,DATABASE_URL", "API_KEY": "your-api-key", "DATABASE_URL": "your-database-url" } } } } ``` **Benefits of NPX approach:** - āœ… **Always latest version** - automatically downloads and runs the newest version - āœ… **No installation required** - no need to install globally or manage versions - āœ… **No maintenance** - automatically gets updates when available - āœ… **Clean system** - doesn't clutter your global npm packages ### Option 2: Global Installation ```bash npm install -g mcp-http-bridge ``` Then use in Cursor configuration: ```json { "mcpServers": { "remote-server": { "command": "mcp-http-bridge", "env": { "MCP_SERVER_URL": "https://your-mcp-server.com/mcp", "MCP_PASS_VARS": "API_KEY,DATABASE_URL", "API_KEY": "your-api-key", "DATABASE_URL": "your-database-url" } } } } ``` ### Option 3: Local Installation ```bash npm install mcp-http-bridge ``` ## Quick Start ### 1. Configure Cursor (Recommended NPX Approach) Add to your Cursor MCP configuration file (`~/.cursor/mcp.json` or similar): ```json { "mcpServers": { "remote-server": { "command": "npx", "args": ["mcp-http-bridge@latest"], "env": { "MCP_SERVER_URL": "https://your-mcp-server.com/mcp", "MCP_PASS_VARS": "API_KEY,DATABASE_URL", "API_KEY": "your-api-key", "DATABASE_URL": "your-database-url" } } } } ``` ### 2. Start Cursor The bridge will automatically: - Connect to your remote MCP server - Handle OAuth authentication if required - Pass specified environment variables as `X-MCP-*` headers - Provide a stdio interface for Cursor ## Configuration ### Required Environment Variables - `MCP_SERVER_URL`: The URL of your remote MCP server ### Optional Environment Variables - `MCP_PASS_VARS`: Comma-separated list of variables to pass (recommended) - `MCP_AUTH_URL`: OAuth authentication URL (if authentication is required) - `MCP_TOKEN_ENDPOINT`: OAuth token endpoint for retrieving and refreshing tokens - `MCP_BRIDGE_DEBUG`: Enable debug logging (`1` or `true`) - `MCP_BRIDGE_LOG_FILE`: Custom debug log file path (default: `./bridge-debug.log`) ## Authentication ### OAuth Flow If your MCP server requires authentication, configure the OAuth settings: ```json { "mcpServers": { "authenticated-server": { "command": "npx", "args": ["mcp-http-bridge@latest"], "env": { "MCP_SERVER_URL": "https://secure-mcp-server.com/mcp/devops", "MCP_AUTH_URL": "https://auth-server.com/auth/mcp-session/devops", "MCP_TOKEN_ENDPOINT": "https://auth-server.com/auth/mcp-session/token/devops", "MCP_PASS_VARS": "API_KEY,DATABASE_URL", "API_KEY": "your-api-key", "DATABASE_URL": "your-database-url" } } } } ``` **OAuth Flow:** 1. Bridge generates a unique auth session ID 2. Opens browser automatically to authentication URL 3. User completes OAuth flow in browser (or cancels with Ctrl+C) 4. Bridge polls token endpoint for access token (5-minute timeout) 5. Token is stored directly in bridge session 6. All requests include standard `Authorization: Bearer <token>` header 7. Automatic token refresh when token expires 8. **Remote MCP servers receive the token via `AUTHORIZATION_HEADER` environment variable** **OAuth Timeout & Cancellation:** - **5-minute timeout**: Authentication automatically fails after 5 minutes - **User cancellation**: Press `Ctrl+C` to cancel OAuth flow anytime - **Graceful cleanup**: Bridge properly cleans up on cancellation or timeout - **Clear error messages**: Specific errors for timeout, cancellation, or connection issues **Token Management:** - **Access Token**: Stored in bridge memory, used for API authentication - **Refresh Token**: Used to automatically refresh expired access tokens - **Token Expiry**: Automatic refresh 1 minute before expiration - **Standard Headers**: Uses OAuth `Authorization: Bearer <token>` header **Token Passing to Remote Servers:** - The bridge automatically passes the `Authorization: Bearer <token>` header to remote MCP servers - Remote servers receive this as the `AUTHORIZATION_HEADER` environment variable - This enables remote servers to use the same OAuth token for their API calls - No additional configuration required - tokens are passed transparently ### Session Management The bridge manages two types of sessions: - **Auth Session ID**: Used for OAuth flow and token retrieval - **MCP Session ID**: Protocol-level session assigned by the server **Authentication Headers:** - `Authorization: Bearer <access_token>` - Standard OAuth authentication - `mcp-session-id: <session_id>` - MCP protocol session (if supported by server) ## Variable Passing Modes ### Explicit Mode (Recommended) Specify exactly which variables to pass: ```json { "env": { "MCP_SERVER_URL": "https://server.com/mcp", "MCP_PASS_VARS": "SQL_SERVER,API_KEY,DATABASE_URL", "SQL_SERVER": "mydb.com", "API_KEY": "abc123", "DATABASE_URL": "postgres://...", "LOGGING_LEVEL": "debug", "CACHE_TTL": "3600" } } ``` **Result**: Only `SQL_SERVER`, `API_KEY`, and `DATABASE_URL` are passed as headers. ### No Variables Mode (Secure Default) If `MCP_PASS_VARS` is not set, no environment variables are passed: ```json { "env": { "MCP_SERVER_URL": "https://server.com/mcp" } } ``` **Result**: Only the bridge connects, no environment variables are passed. ## Header Conversion Environment variables are converted to HTTP headers: - `SQL_SERVER=mydb.com` → `X-MCP-SQL-SERVER: mydb.com` - `API_KEY=abc123` → `X-MCP-API-KEY: abc123` - `DATABASE_URL=postgres://...` → `X-MCP-DATABASE-URL: postgres://...` ## System Variables These variables are **never passed** to remote servers: - System paths: `PATH`, `HOME`, `USER`, etc. - Node.js variables: `NODE_ENV`, `NODE_PATH`, `npm_*`, etc. - Windows variables: `USERPROFILE`, `PROGRAMFILES`, etc. - Bridge variables: `MCP_SERVER_URL`, `MCP_PASS_VARS`, `MCP_AUTH_URL`, `MCP_TOKEN_ENDPOINT` ## Debug Mode Enable detailed logging for troubleshooting: ```json { "env": { "MCP_SERVER_URL": "https://server.com/mcp", "MCP_BRIDGE_DEBUG": "1" } } ``` **Debug Features:** - Console logging to stderr - File logging to `./bridge-debug.log` (or custom path via `MCP_BRIDGE_LOG_FILE`) - Environment variable analysis - HTTP request/response tracing - Session management details - OAuth token lifecycle logging ## Examples ### Simple HTTP MCP Server Example Try the included example server to see how the bridge works: 1. **Run the example server**: ```bash cd examples npm install npm start ``` 2. **Configure Cursor**: ```json { "mcpServers": { "simple-example": { "command": "npx", "args": ["mcp-http-bridge@latest"], "env": { "MCP_SERVER_URL": "http://localhost:3001/mcp", "MCP_PASS_VARS": "API_KEY,DATABASE_URL,SERVICE_NAME", "API_KEY": "test-api-key-123", "DATABASE_URL": "postgres://localhost:5432/testdb", "SERVICE_NAME": "example-service" } } } } ``` 3. **Test the tools**: - `get_environment` - See how headers become environment variables - `echo_message` - Test basic connectivity - `test_api_connection` - Verify authentication flow The example demonstrates: - āœ… **Header conversion**: `X-MCP-API-KEY` → `process.env.API_KEY` - āœ… **OAuth handling**: `Authorization: Bearer <token>` → `process.env.AUTHORIZATION_HEADER` - āœ… **Security filtering**: Sensitive variables are masked - āœ… **Standard MCP protocol**: Proper JSON-RPC implementation See [`examples/README.md`](examples/README.md) for detailed documentation. ### Azure DevOps with OAuth ```json { "mcpServers": { "azure-devops": { "command": "npx", "args": ["mcp-http-bridge@latest"], "env": { "MCP_SERVER_URL": "https://devops-mcp.example.com/mcp/devops", "MCP_AUTH_URL": "https://auth.example.com/auth/mcp-session/devops", "MCP_TOKEN_ENDPOINT": "https://auth.example.com/auth/mcp-session/token/devops", "MCP_PASS_VARS": "AZURE_DEVOPS_ORG,AZURE_DEVOPS_PROJECT", "AZURE_DEVOPS_ORG": "myorg", "AZURE_DEVOPS_PROJECT": "MyProject" } } } } ``` ### SQL Server Connection ```json { "mcpServers": { "remote-sql": { "command": "npx", "args": ["mcp-http-bridge@latest"], "env": { "MCP_SERVER_URL": "https://sql-mcp.example.com/mcp", "MCP_PASS_VARS": "SQL_SERVER,SQL_DATABASE,SQL_USER,SQL_PASSWORD", "SQL_SERVER": "mydb.database.windows.net", "SQL_DATABASE": "production", "SQL_USER": "admin", "SQL_PASSWORD": "secret123" } } } } ``` ### Web Search Service ```json { "mcpServers": { "remote-search": { "command": "npx", "args": ["mcp-http-bridge@latest"], "env": { "MCP_SERVER_URL": "https://search-mcp.example.com/mcp", "MCP_PASS_VARS": "GOOGLE_API_KEY,SEARCH_ENGINE_ID", "GOOGLE_API_KEY": "your-google-api-key", "SEARCH_ENGINE_ID": "your-search-engine-id" } } } } ``` ### Debug Mode Example ```json { "mcpServers": { "debug-server": { "command": "npx", "args": ["mcp-http-bridge@latest"], "env": { "MCP_SERVER_URL": "https://server.com/mcp", "MCP_BRIDGE_DEBUG": "true", "MCP_PASS_VARS": "API_KEY", "API_KEY": "test-key" } } } } ``` ## Server-Sent Events Support The bridge automatically handles both response types: - **JSON responses**: Standard MCP JSON-RPC responses - **SSE responses**: Server-Sent Events for streaming data SSE responses are parsed automatically: ``` event: message data: {"jsonrpc": "2.0", "result": {...}} ``` ## Troubleshooting ### Connection Issues ```bash # Check if the remote server is accessible curl -X POST https://your-mcp-server.com/mcp \ -H "Content-Type: application/json" \ -d '{"method": "tools/list"}' ``` ### Authentication Issues 1. **Check OAuth URL**: Verify `MCP_AUTH_URL` is correct 2. **Token Endpoint**: Ensure `MCP_TOKEN_ENDPOINT` is accessible 3. **Browser Access**: Check if browser opens automatically 4. **Session Timeout**: OAuth flow times out after 5 minutes 5. **Token Refresh**: Automatic refresh handles expired tokens ### Debug Mode Enable debug logging to see detailed information: ```json { "env": { "MCP_BRIDGE_DEBUG": "1" } } ``` **Debug Output:** ``` šŸ”„ BRIDGE DEBUG: Bridge starting up... šŸ” Environment variables check: šŸŒ‰ Starting Cursor-HTTP bridge to: https://server.com/mcp šŸ” Authentication required. Auth Session ID: mcp-bridge-1234567890-abc123 🌐 Opening browser for authentication... šŸŽ« Access token retrieved successfully šŸŽ« Token expires at: 2024-01-15T14:30:00.000Z šŸ”„ Refresh token available: true āœ… Authentication completed successfully! šŸ” Using OAuth Bearer token šŸ”§ Passing 2 environment variables as headers šŸ”Œ Bridge ready - Cursor can now connect via stdio ``` ### Common Issues 1. **"MCP_SERVER_URL is required"** - Set the `MCP_SERVER_URL` environment variable 2. **"Failed to connect to remote server"** - Check that the server URL is correct and accessible - Verify the server is running and accepting connections 3. **"Authentication timeout"** - Complete OAuth flow within 5 minutes - Check `MCP_TOKEN_ENDPOINT` is accessible - Press `Ctrl+C` to cancel and retry if stuck 4. **"MCP_TOKEN_ENDPOINT required for authentication"** - Set the `MCP_TOKEN_ENDPOINT` environment variable for OAuth 5. **"No tools/resources available"** - Check that required environment variables are being passed - Verify the remote server has the expected configuration 6. **SSE parsing errors** - Server may be sending malformed SSE responses - Enable debug mode to see raw response content 7. **Token refresh failures** - Bridge automatically retries with refreshed tokens - Check debug logs for token refresh attempts 8. **"Continuous token polling in logs"** - Old bridge processes may still be running in background - Kill all Node.js processes: `taskkill /f /im node.exe` (Windows) - Or restart Cursor to clean up all MCP processes - Check for leftover `mcp-bridge-*` session IDs in logs ## Security Considerations - **Never hardcode credentials** in configuration files - Use **environment variables** for sensitive data - Use **`MCP_PASS_VARS`** to control exactly what gets sent - Deploy remote servers with **HTTPS** in production - Implement **OAuth authentication** for production servers - **Token storage** is in-memory only (not persisted to disk) - **Session management** prevents unauthorized access - **Standard OAuth headers** for better security compliance ## Requirements - Node.js 18.0.0 or higher - Remote MCP server supporting Streamable HTTP transport - Modern browser for OAuth authentication (if required) - OAuth token endpoint supporting `authorization_code` and `refresh_token` grants ## Architecture ``` Cursor (stdio) ←→ MCP HTTP Bridge ←→ Remote MCP Server (HTTP/SSE) ↓ ↑ OAuth Provider Authorization: Bearer <token> ↓ Token Endpoint ``` **Components:** - **Cursor Interface**: stdio-based MCP client - **HTTP Bridge**: Converts stdio ↔ HTTP with OAuth authentication - **Remote Server**: HTTP-based MCP server expecting Bearer tokens - **OAuth Provider**: Handles authentication flow - **Token Endpoint**: Issues and refreshes OAuth tokens **Authentication Flow:** 1. User authenticates via OAuth provider 2. Bridge retrieves tokens from token endpoint 3. Bridge stores tokens in memory 4. All requests include `Authorization: Bearer <token>` header 5. Bridge automatically refreshes expired tokens 6. Remote MCP servers receive the token via `AUTHORIZATION_HEADER` environment variable ## License MIT ## Contributing Issues and pull requests welcome at: https://github.com/your-username/mcp-http-bridge