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
Markdown
# 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