# MCP Proxy

<div align="center">

**一个强大的 MCP (Model Context Protocol) 代理服务器，支持直连和反向连接两种模式**

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)

[English](#) | [中文文档](#)

</div>

---

## 📖 简介

MCP Proxy 是一个透明的 MCP 协议代理服务器，基于 FastAPI 和 MCP SDK 构建。它解决了在复杂网络环境下使用 MCP 服务的难题，特别适合需要统一入口、负载均衡或穿透内网的场景。

### ✨ 核心特性

- 🔄 **双模式支持** - 直连模式 + 反向连接模式
- 🌐 **内网穿透** - 无需公网 IP，内网 MCP Server 也能被外部访问
- 🔐 **Token 认证** - 安全的连接器注册机制
- 📡 **SSE 流式传输** - 完整支持 MCP 协议的实时通信
- 🔌 **WebSocket 通道** - 高效的反向连接通信
- 📊 **监控完善** - 提供状态查询、健康检查、统计信息等 API
- ⚡ **异步高性能** - 基于 FastAPI 异步架构
- 🛡️ **会话管理** - 自动管理客户端与后端连接
- 📝 **详细日志** - 完整的调用链路追踪
- 🔧 **配置灵活** - 支持环境变量和配置文件

---

## 🏗️ 架构设计

### 直连模式（Direct Mode）

适用于后端 MCP Server 可直接访问的场景。

```mermaid
graph LR
    A[Cursor/Client] -->|SSE + POST| B[MCP Proxy]
    B -->|HTTP| C[MCP Server]
    C -->|SSE Response| B
    B -->|SSE Stream| A
    
    style A fill:#e1f5ff
    style B fill:#fff4e6
    style C fill:#f3e5f5
```

**特点**：
- 简单直接，延迟最低
- 适合同一网络或公网可访问的 MCP Server

### 反向连接模式（Reverse Connection Mode）

适用于内网 MCP Server 需要被外网访问的场景。

```mermaid
graph TB
    Client[Cursor/Client<br/>公网或任意位置]
    Proxy[MCP Proxy<br/>公网服务器]
    Connector[MCP Connector<br/>内网环境]
    MCP[MCP Server<br/>内网服务]
    
    Client -->|"1. SSE Connect<br/>backend_id=xxx"| Proxy
    Connector -->|"2. WebSocket<br/>主动连接"| Proxy
    Connector <-->|"3. 本地通信<br/>HTTP"| MCP
    
    Proxy -->|"4. 路由请求<br/>via WebSocket"| Connector
    Connector -->|"5. 响应返回<br/>via WebSocket"| Proxy
    Proxy -->|"6. SSE 推送"| Client
    
    style Client fill:#e3f2fd
    style Proxy fill:#fff3e0
    style Connector fill:#f3e5f5
    style MCP fill:#e8f5e9
```

**特点**：
- ✅ 内网 MCP Server 无需公网 IP
- ✅ 无需配置端口转发或 NAT
- ✅ 防火墙友好（只需出站连接）
- ✅ 支持多个内网 MCP Server 同时连接

### 消息流程详解

```mermaid
sequenceDiagram
    participant C as 客户端
    participant P as 代理服务器
    participant Conn as 连接器
    participant M as MCP Server
    
    Note over Conn,M: 启动阶段
    Conn->>M: 1. 连接本地 MCP
    Conn->>P: 2. WebSocket 连接
    Conn->>P: 3. 注册 (backend_id + token)
    P-->>Conn: 4. 注册成功
    
    Note over C,M: 使用阶段
    C->>P: 5. GET /sse?backend_id=xxx
    P-->>C: 6. SSE Stream + session_id
    
    C->>P: 7. POST /messages (initialize)
    P->>Conn: 8. WebSocket 转发
    Conn->>M: 9. 创建 SSE 连接
    M-->>Conn: 10. session_id + endpoint
    Conn->>M: 11. POST /messages (initialize)
    M-->>Conn: 12. SSE 响应
    Conn-->>P: 13. WebSocket 转发
    P-->>C: 14. SSE 推送
    
    C->>P: 15. POST /messages (tools/list)
    P->>Conn: 16. WebSocket 转发
    Conn->>M: 17. POST /messages (tools/list)
    M-->>Conn: 18. SSE 响应
    Conn-->>P: 19. WebSocket 转发
    P-->>C: 20. SSE 推送
```

---

## 🚀 快速开始

### 前置要求

- Python 3.10+
- [uv](https://github.com/astral-sh/uv) (推荐) 或 pip

### 安装

```bash
# 克隆仓库
git clone https://github.com/hyx-cn/mcp-proxy.git
cd mcp-proxy

# 安装依赖
uv pip install -r requirements.txt --index-url https://pypi.org/simple

# 或使用 pip
pip install -r requirements.txt
```

### 配置

```bash
# 复制配置文件
cp config/.env.example .env

# 编辑配置
vim .env
```

基础配置：

```bash
# .env
HOST=0.0.0.0
PORT=10086
DEFAULT_BACKEND_URL=http://127.0.0.1:9012

# 反向连接配置（可选）
ENABLE_REVERSE_CONNECTOR=true
# CONNECTOR_TOKENS=token1,token2,token3
```

### 启动代理服务器

```bash
# 方式1: 使用启动脚本
bash scripts/start_proxy.sh

# 方式2: 直接运行
uv run python -m src.proxy

# 方式3: 指定端口
python -m src.proxy 8080
```

服务器启动后访问：http://localhost:10086

---

## 📦 使用方式

### 模式 1: 直连模式

适用于 MCP Server 可直接访问的场景。

#### 1. 启动后端 MCP Server

```bash
# 使用示例服务器
uv run python examples/simple_mcp_server.py
```

#### 2. 在 Cursor 中配置

```json
{
  "mcpServers": {
    "my-server": {
      "url": "http://localhost:10086/sse",
      "transport": "sse"
    }
  }
}
```

或指定特定后端：

```json
{
  "mcpServers": {
    "custom-backend": {
      "url": "http://localhost:10086/sse?backend=http://other-server:3000",
      "transport": "sse"
    }
  }
}
```

### 模式 2: 反向连接模式 ⭐

适用于内网 MCP Server 需要被外网访问的场景。

#### 1. 启动后端 MCP Server（内网）

```bash
# 在内网机器上
uv run python examples/simple_mcp_server.py
```

#### 2. 配置连接器

```bash
# 复制配置文件
cp config/connector_config.yaml.example config/connector_config.yaml

# 编辑配置
vim config/connector_config.yaml
```

```yaml
# connector_config.yaml
proxy_url: ws://your-proxy-server.com:10086/ws/connector
backend_id: office-server-1
token: your-secret-token-123
local_mcp_url: http://127.0.0.1:9012
```

#### 3. 启动连接器（内网）

```bash
# 方式1: 使用启动脚本
bash scripts/start_connector.sh config/connector_config.yaml

# 方式2: 直接运行
uv run python -m src.connector --config config/connector_config.yaml
```

#### 4. 验证连接

```bash
# 查看已连接的后端
curl http://your-proxy-server.com:10086/connectors
```

#### 5. 在 Cursor 中配置

```json
{
  "mcpServers": {
    "internal-server": {
      "url": "http://your-proxy-server.com:10086/sse?backend_id=office-server-1",
      "transport": "sse"
    }
  }
}
```

---

## 🔧 API 文档

### 代理服务器端点

| 端点 | 方法 | 说明 | 模式 |
|------|------|------|------|
| `/sse` | GET | SSE 流连接 | 直连 |
| `/sse?backend=<url>` | GET | 指定后端的 SSE 连接 | 直连 |
| `/sse?backend_id=<id>` | GET | 反向连接的 SSE | 反向 |
| `/messages?session_id=<id>` | POST | 发送 JSON-RPC 消息 | 通用 |
| `/connectors` | GET | 列出反向连接器 | 监控 |
| `/sessions` | GET | 列出所有会话 | 监控 |
| `/health` | GET | 健康检查 | 监控 |
| `/stats` | GET | 详细统计信息 | 监控 |
| `/ws/connector` | WebSocket | 连接器注册端点 | 反向 |

### WebSocket 消息格式

#### 注册消息（连接器 → 代理）

```json
{
  "type": "register",
  "backend_id": "office-server-1",
  "token": "your-secret-token",
  "metadata": {
    "version": "1.0.0",
    "local_mcp_url": "http://127.0.0.1:9012"
  }
}
```

#### 请求转发（代理 → 连接器）

```json
{
  "type": "request",
  "backend_id": "office-server-1",
  "session_id": "client-session-id",
  "data": {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/list"
  }
}
```

#### 响应转发（连接器 → 代理）

```json
{
  "type": "response",
  "backend_id": "office-server-1",
  "session_id": "client-session-id",
  "data": "data: {\"jsonrpc\":\"2.0\",\"id\":1,\"result\":{...}}"
}
```

---

## 📊 监控和管理

### 查看系统状态

```bash
# 健康检查
curl http://localhost:10086/health

# 输出示例：
{
  "status": "healthy",
  "timestamp": "2026-02-15T19:00:00.000000",
  "stats": {
    "direct_sessions": 2,
    "reverse_sessions": 3,
    "reverse_connectors": 2
  }
}
```

### 查看连接器

```bash
# 列出所有反向连接器
curl http://localhost:10086/connectors | python3 -m json.tool

# 输出示例：
{
  "count": 2,
  "connectors": {
    "office-server": {
      "backend_id": "office-server",
      "is_active": true,
      "connected_at": "2026-02-15T10:00:00.000000",
      "uptime_seconds": 3600.5,
      "metadata": {...}
    },
    "home-server": {
      "backend_id": "home-server",
      "is_active": true,
      "connected_at": "2026-02-15T11:00:00.000000",
      "uptime_seconds": 1800.3,
      "metadata": {...}
    }
  }
}
```

### 查看会话

```bash
# 查看所有活跃会话
curl http://localhost:10086/sessions | python3 -m json.tool
```

### 详细统计

```bash
# 获取详细统计信息
curl http://localhost:10086/stats | python3 -m json.tool
```

---

## 🌟 使用场景

### 场景 1: 统一入口

多个 MCP Server 通过一个代理对外提供服务。

```json
{
  "mcpServers": {
    "github": {
      "url": "http://proxy.example.com:10086/sse?backend=http://github-mcp:3000",
      "transport": "sse"
    },
    "filesystem": {
      "url": "http://proxy.example.com:10086/sse?backend=http://fs-mcp:3001",
      "transport": "sse"
    }
  }
}
```

### 场景 2: 内网穿透

办公室内网的 MCP Server，在家里也能访问。

```
办公室内网:
  - MCP Server (127.0.0.1:9012)
  - Connector (连接到公网代理)

家里/外网:
  - Cursor 连接到公网代理
  - 通过 backend_id 访问办公室的 MCP Server
```

### 场景 3: 多环境切换

在不同环境的 MCP Server 之间快速切换。

```json
{
  "mcpServers": {
    "dev": {
      "url": "http://proxy.com:10086/sse?backend_id=dev-server",
      "transport": "sse"
    },
    "staging": {
      "url": "http://proxy.com:10086/sse?backend_id=staging-server",
      "transport": "sse"
    },
    "prod": {
      "url": "http://proxy.com:10086/sse?backend_id=prod-server",
      "transport": "sse"
    }
  }
}
```

---

## 🔐 安全配置

### Token 认证

在代理服务器的 `.env` 中配置允许的 tokens：

```bash
# .env
CONNECTOR_TOKENS=secure-token-1,secure-token-2,secure-token-3
```

在连接器配置中使用对应的 token：

```yaml
# connector_config.yaml
token: secure-token-1
```

### 后端白名单

限制允许代理的后端地址：

```bash
# .env
ALLOWED_BACKENDS=http://127.0.0.1:9012,http://trusted-server.com:3000
```

### HTTPS/WSS

生产环境强烈建议使用加密连接：

```yaml
# 连接器配置
proxy_url: wss://proxy.example.com:10086/ws/connector
```

使用 Nginx 或 Caddy 配置 SSL：

```nginx
server {
    listen 443 ssl;
    server_name proxy.example.com;
    
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
    
    location / {
        proxy_pass http://127.0.0.1:10086;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}
```

---

## 📚 文档

- [反向连接器指南](docs/CONNECTOR_README.md) - 详细的反向连接配置
- [架构设计](docs/ARCHITECTURE.md) - 技术架构和实现细节
- [配置指南](docs/CONFIG_GUIDE.md) - 所有配置项说明
- [部署指南](docs/REVERSE_QUICKSTART.md) - 生产环境部署

---

## 🛠️ 开发

### 项目结构

```
mcp-proxy/
├── src/                        # 源代码
│   ├── __init__.py
│   ├── proxy.py                # 代理服务器
│   ├── connector.py            # 反向连接器
│   ├── reverse_connector.py    # 连接器管理模块
│   └── config.py               # 配置管理
├── config/                     # 配置文件
│   ├── .env.example
│   └── connector_config.yaml.example
├── examples/                   # 示例
│   └── simple_mcp_server.py
├── tests/                      # 测试
│   ├── test_reverse_tools.py
│   └── test_reverse_connector.sh
├── scripts/                    # 工具脚本
│   ├── start_proxy.sh
│   └── start_connector.sh
├── docs/                       # 文档
│   ├── QUICKSTART.md
│   ├── CONNECTOR_README.md
│   └── ARCHITECTURE.md
├── requirements.txt            # 依赖
├── LICENSE                     # MIT 许可证
├── .gitignore
└── README.md
```

### 运行测试

```bash
# 测试反向连接器
bash tests/test_reverse_connector.sh

# Python 测试脚本
uv run python tests/test_reverse_tools.py
```

### 调试

启用 DEBUG 日志：

```bash
# .env
LOG_LEVEL=DEBUG
```

查看详细日志：

```bash
# 代理服务器日志在终端输出
# 连接器日志在终端输出

# 或重定向到文件
python -m src.proxy > proxy.log 2>&1 &
python -m src.connector --config config/connector_config.yaml > connector.log 2>&1 &
```

---

## 🚢 部署

### Docker 部署（推荐）

#### 代理服务器

```dockerfile
FROM python:3.11-slim

WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY src/ ./src/
COPY .env .

EXPOSE 10086

CMD ["python", "-m", "src.proxy"]
```

```bash
docker build -t mcp-proxy .
docker run -d -p 10086:10086 --name mcp-proxy \
  -v $(pwd)/.env:/app/.env \
  mcp-proxy
```

#### 连接器

```dockerfile
FROM python:3.11-slim

WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir websockets pyyaml httpx

COPY src/connector.py ./src/
COPY config/connector_config.yaml ./config/

CMD ["python", "-m", "src.connector", "--config", "config/connector_config.yaml"]
```

```bash
docker build -f Dockerfile.connector -t mcp-connector .
docker run -d --name mcp-connector \
  --network host \
  -v $(pwd)/config:/app/config \
  mcp-connector
```

### Systemd 部署

参见 [docs/CONNECTOR_README.md](docs/CONNECTOR_README.md) 中的详细部署指南。

---

## 🤝 贡献

欢迎贡献！请遵循以下步骤：

1. Fork 本仓库
2. 创建特性分支 (`git checkout -b feature/AmazingFeature`)
3. 提交更改 (`git commit -m 'Add some AmazingFeature'`)
4. 推送到分支 (`git push origin feature/AmazingFeature`)
5. 开启 Pull Request

---

## 📄 许可证

本项目采用 MIT 许可证 - 查看 [LICENSE](LICENSE) 文件了解详情。

---

## 🙏 致谢

- [FastAPI](https://fastapi.tiangolo.com/) - 现代化的 Web 框架
- [MCP SDK](https://github.com/modelcontextprotocol/python-sdk) - Model Context Protocol Python SDK
- [websockets](https://websockets.readthedocs.io/) - WebSocket 客户端和服务器

---

## 📮 联系方式

- Issues: [GitHub Issues](https://github.com/hyx-cn/mcp-proxy/issues)
- Discussions: [GitHub Discussions](https://github.com/hyx-cn/mcp-proxy/discussions)

---

## ⭐ Star History

如果这个项目对你有帮助，请给它一个 star ⭐️

---

<div align="center">
Made with ❤️ by MCP Proxy Contributors
</div>
