Add proxy support for MCP server connections
This commit is contained in:
parent
a9c76eca21
commit
4ab833ca7b
4 changed files with 116 additions and 16 deletions
|
|
@ -301,14 +301,16 @@ and injected into the context for a configured number of turns (`ttl`).
|
|||
| `env_file` | string | no | Path to environment file for stdio process |
|
||||
| `url` | string | sse/http | Endpoint URL for `sse`/`http` transport |
|
||||
| `headers` | object | no | HTTP headers for `sse`/`http` transport |
|
||||
| `proxy` | string | no | HTTP proxy URL (http/https/socks5/socks5h). For `sse`/`http`: used for HTTP requests. For `stdio`: sets `HTTP_PROXY`/`HTTPS_PROXY` env vars for the subprocess. When empty, uses environment proxy settings. |
|
||||
|
||||
### Transport Behavior
|
||||
|
||||
- If `type` is omitted, transport is auto-detected:
|
||||
- `url` is set → `sse`
|
||||
- `command` is set → `stdio`
|
||||
- `http` and `sse` both use `url` + optional `headers`.
|
||||
- `env` and `env_file` are only applied to `stdio` servers.
|
||||
- `http` and `sse` both use `url` + optional `headers` and `proxy`.
|
||||
- `env`, `env_file`, and `proxy` are only applied to `stdio` servers (via environment variables).
|
||||
- All transport types support the `proxy` option. Supports http, https, socks5, and socks5h schemes.
|
||||
|
||||
### Configuration Examples
|
||||
|
||||
|
|
@ -357,6 +359,31 @@ and injected into the context for a configured number of turns (`ttl`).
|
|||
}
|
||||
```
|
||||
|
||||
#### 2.1) Remote MCP server with proxy
|
||||
|
||||
```json
|
||||
{
|
||||
"tools": {
|
||||
"mcp": {
|
||||
"enabled": true,
|
||||
"servers": {
|
||||
"remote-mcp-behind-proxy": {
|
||||
"enabled": true,
|
||||
"type": "sse",
|
||||
"url": "https://internal-mcp.example.com/mcp",
|
||||
"proxy": "socks5://127.0.0.1:1080",
|
||||
"headers": {
|
||||
"Authorization": "Bearer YOUR_TOKEN"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Supported proxy schemes: `http`, `https`, `socks5`, `socks5h`. When `proxy` is not set, the system environment proxy settings (`HTTP_PROXY`, `HTTPS_PROXY`, `NO_PROXY`) are used.
|
||||
|
||||
#### 3) Massive MCP setup with Tool Discovery enabled
|
||||
|
||||
*In this example, the LLM will only see the `tool_search_tool_bm25`. It will search and unlock Github or Postgres tools
|
||||
|
|
|
|||
|
|
@ -277,14 +277,16 @@ LLM 不会加载所有工具,而是获得一个轻量级搜索工具(使用
|
|||
| `env_file` | string | 否 | stdio 进程的环境文件路径 |
|
||||
| `url` | string | sse/http | `sse`/`http` 传输的端点 URL |
|
||||
| `headers` | object | 否 | `sse`/`http` 传输的 HTTP 头 |
|
||||
| `proxy` | string | 否 | HTTP 代理 URL(支持 http/https/socks5/socks5h)。对于 `sse`/`http`:用于 HTTP 请求。对于 `stdio`:设置子进程的 `HTTP_PROXY`/`HTTPS_PROXY` 环境变量。为空时使用系统环境代理设置。 |
|
||||
|
||||
### 传输行为
|
||||
|
||||
- 如果省略 `type`,传输方式将自动检测:
|
||||
- 设置了 `url` → `sse`
|
||||
- 设置了 `command` → `stdio`
|
||||
- `http` 和 `sse` 都使用 `url` + 可选的 `headers`。
|
||||
- `env` 和 `env_file` 仅应用于 `stdio` 服务器。
|
||||
- `http` 和 `sse` 都使用 `url` + 可选的 `headers` 和 `proxy`。
|
||||
- `env`、`env_file` 和 `proxy` 仅应用于 `stdio` 服务器(通过环境变量)。
|
||||
- 所有传输类型都支持 `proxy` 选项,支持 http、https、socks5 和 socks5h 协议。
|
||||
|
||||
### 配置示例
|
||||
|
||||
|
|
@ -333,6 +335,31 @@ LLM 不会加载所有工具,而是获得一个轻量级搜索工具(使用
|
|||
}
|
||||
```
|
||||
|
||||
#### 2.1) 通过代理连接远程 MCP 服务器
|
||||
|
||||
```json
|
||||
{
|
||||
"tools": {
|
||||
"mcp": {
|
||||
"enabled": true,
|
||||
"servers": {
|
||||
"remote-mcp-behind-proxy": {
|
||||
"enabled": true,
|
||||
"type": "sse",
|
||||
"url": "https://internal-mcp.example.com/mcp",
|
||||
"proxy": "socks5://127.0.0.1:1080",
|
||||
"headers": {
|
||||
"Authorization": "Bearer YOUR_TOKEN"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
支持的代理协议:`http`、`https`、`socks5`、`socks5h`。未设置 `proxy` 时,使用系统环境代理设置(`HTTP_PROXY`、`HTTPS_PROXY`、`NO_PROXY`)。
|
||||
|
||||
#### 3) 启用工具发现的大规模 MCP 设置
|
||||
|
||||
*在此示例中,LLM 只会看到 `tool_search_tool_bm25`。它将仅在用户请求时动态搜索并解锁 Github 或 Postgres 工具。*
|
||||
|
|
|
|||
|
|
@ -899,6 +899,8 @@ type MCPServerConfig struct {
|
|||
URL string `json:"url,omitempty"`
|
||||
// Headers are HTTP headers to send with requests (sse/http only)
|
||||
Headers map[string]string `json:"headers,omitempty"`
|
||||
// Proxy is an optional proxy URL for SSE/HTTP transport (http/https/socks5/socks5h)
|
||||
Proxy string `json:"proxy,omitempty"`
|
||||
}
|
||||
|
||||
// MCPConfig defines configuration for all MCP servers
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
|
|
@ -290,6 +291,7 @@ func (m *Manager) ConnectServer(
|
|||
"server": name,
|
||||
"url": cfg.URL,
|
||||
"disableStandaloneSSE": disableStandaloneSSE,
|
||||
"proxy": cfg.Proxy,
|
||||
})
|
||||
|
||||
sseTransport := &mcp.StreamableClientTransport{
|
||||
|
|
@ -297,12 +299,24 @@ func (m *Manager) ConnectServer(
|
|||
DisableStandaloneSSE: disableStandaloneSSE,
|
||||
}
|
||||
|
||||
// Add custom headers if provided
|
||||
// Create HTTP client with headers and optional proxy
|
||||
needsCustomClient := len(cfg.Headers) > 0 || cfg.Proxy != ""
|
||||
if needsCustomClient {
|
||||
transport := &http.Transport{
|
||||
Proxy: func(req *http.Request) (*url.URL, error) {
|
||||
if cfg.Proxy != "" {
|
||||
return url.Parse(cfg.Proxy)
|
||||
}
|
||||
// Fall back to environment proxy settings
|
||||
return http.ProxyFromEnvironment(req)
|
||||
},
|
||||
}
|
||||
|
||||
// Wrap with header transport if custom headers are provided
|
||||
if len(cfg.Headers) > 0 {
|
||||
// Create a custom HTTP client with header-injecting transport
|
||||
sseTransport.HTTPClient = &http.Client{
|
||||
Transport: &headerTransport{
|
||||
base: http.DefaultTransport,
|
||||
base: transport,
|
||||
headers: cfg.Headers,
|
||||
},
|
||||
}
|
||||
|
|
@ -311,6 +325,19 @@ func (m *Manager) ConnectServer(
|
|||
"server": name,
|
||||
"header_count": len(cfg.Headers),
|
||||
})
|
||||
} else {
|
||||
sseTransport.HTTPClient = &http.Client{
|
||||
Transport: transport,
|
||||
}
|
||||
}
|
||||
|
||||
if cfg.Proxy != "" {
|
||||
logger.DebugCF("mcp", "Using custom proxy for MCP server",
|
||||
map[string]any{
|
||||
"server": name,
|
||||
"proxy": cfg.Proxy,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
transport = sseTransport
|
||||
|
|
@ -322,6 +349,7 @@ func (m *Manager) ConnectServer(
|
|||
map[string]any{
|
||||
"server": name,
|
||||
"command": cfg.Command,
|
||||
"proxy": cfg.Proxy,
|
||||
})
|
||||
// Create command with context
|
||||
cmd := exec.CommandContext(ctx, cfg.Command, cfg.Args...)
|
||||
|
|
@ -359,6 +387,22 @@ func (m *Manager) ConnectServer(
|
|||
envMap[k] = v
|
||||
}
|
||||
|
||||
// Set proxy environment variables for stdio transport
|
||||
// This allows the subprocess to make HTTP requests through the proxy
|
||||
if cfg.Proxy != "" {
|
||||
envMap["HTTP_PROXY"] = cfg.Proxy
|
||||
envMap["HTTPS_PROXY"] = cfg.Proxy
|
||||
// By default, don't proxy localhost/loopback addresses
|
||||
if _, exists := envMap["NO_PROXY"]; !exists {
|
||||
envMap["NO_PROXY"] = "localhost,127.0.0.1,::1"
|
||||
}
|
||||
logger.DebugCF("mcp", "Added proxy environment variables for stdio transport",
|
||||
map[string]any{
|
||||
"server": name,
|
||||
"proxy": cfg.Proxy,
|
||||
})
|
||||
}
|
||||
|
||||
// Convert map to slice
|
||||
env := make([]string, 0, len(envMap))
|
||||
for k, v := range envMap {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue