# AsyncMCP Proxy

The AsyncMCP Proxy module provides a bridge between standard MCP transports (StreamableHTTP/stdio) and asyncmcp's asynchronous transports (SQS, SNS+SQS, Webhook). This enables MCP clients to connect to services running on async transports without modification.

## Overview

The proxy server:
- Exposes a standard MCP StreamableHTTP endpoint
- Forwards requests to configured asyncmcp backend transports
- Streams responses back to clients using Server-Sent Events (SSE)
- Supports session isolation for concurrent clients
- Provides optional authentication and CORS support

## Architecture

```
MCP Client → StreamableHTTP → Proxy Server → AsyncMCP Transport → MCP Server
                                    ↓
                              ProxySessionManager
                                    ↓
                              ProxyClient (Backend Adapter)
```

## Usage

### Basic Proxy Server

```python
from asyncmcp.proxy import create_proxy_server
from asyncmcp.sqs.utils import SqsClientConfig
import boto3

# Configure backend
backend_config = SqsClientConfig(
    read_queue_url="https://sqs.us-east-1.amazonaws.com/123/requests",
    response_queue_url="https://sqs.us-east-1.amazonaws.com/123/responses"
)

# Create and run proxy
proxy = create_proxy_server(
    backend_transport="sqs",
    backend_config=backend_config,
    backend_clients={"sqs_client": boto3.client("sqs")},
    port=8080
)

await proxy.run()
```

### Advanced Configuration

```python
from asyncmcp.proxy import ProxyConfig, ProxyServer

config = ProxyConfig(
    # Server settings
    host="0.0.0.0",
    port=8080,
    server_path="/mcp",
    
    # Backend settings
    backend_transport="sns_sqs",
    backend_config=sns_sqs_config,
    backend_clients={"sqs_client": sqs, "sns_client": sns},
    
    # Session management
    session_timeout=300.0,
    max_sessions=100,
    stateless=False,
    
    # Security
    cors_origins=["http://localhost:3000"],
    auth_enabled=True,
    auth_token="secret-token"
)

server = ProxyServer(config)
await server.run()
```

### Client Connection

MCP clients connect to the proxy using standard StreamableHTTP:

```javascript
// JavaScript/TypeScript client example
const client = new MCPClient({
    transport: {
        type: "streamable-http",
        url: "http://localhost:8080/mcp"
    }
});

// Use the client normally
const tools = await client.listTools();
```

## Features

### Session Management
- Each client connection gets an isolated backend session
- Sessions are automatically cleaned up on disconnect
- Configurable session limits and timeouts

### Error Handling
- Graceful error propagation from backend
- Client-friendly error messages
- Automatic reconnection support

## Limitations

### Multiple Concurrent Sessions
The proxy has limited support for multiple concurrent sessions from the same proxy instance when using async transports like SQS. This limitation stems from the MCP protocol design:

- Session IDs are generated by the server (not the client) and returned in the initialize response
- With async transports, when multiple proxy sessions share a backend connection, initialize responses cannot be reliably correlated back to the originating proxy session
- Each proxy session effectively requires its own backend connection with dedicated response queues

This means that for SQS/SNS+SQS transports, each new session from the proxy will create a separate backend connection rather than sharing a single connection. This is by design to ensure proper message routing and session isolation.

## Supported Backends

The proxy supports all asyncmcp transports:

- **SQS**: AWS Simple Queue Service
- **SNS+SQS**: AWS SNS topics with SQS queues
- **Webhook**: HTTP webhook-based transport
- **StreamableHTTP+Webhook**: Hybrid transport

## Example: Running the Proxy

See `examples/proxy_server.py` for a complete example:

```bash
# Start proxy with SQS backend
python examples/proxy_server.py --backend sqs

# With authentication
python examples/proxy_server.py --backend sqs --auth-token "secret"

# With CORS for browser clients
python examples/proxy_server.py --backend sqs --cors-origin "http://localhost:3000"
```

## Testing

Run the proxy tests:

```bash
pytest tests/proxy/
```
