Skip to content

Commit 9f3d843

Browse files
authored
šŸ› Bugfix: Fix MCP integration by ignoring proxy environment variables (#3121)
* Bugfix: Fix MCP integration by ignoring proxy environment variables * ę–°å¢žpandasä¾čµ– * Revert "ę–°å¢žpandasä¾čµ–" This reverts commit d3af8d5. * Bugfix: resolve circular dependency * fix ut * äæ®å¤UT
1 parent 622ffdd commit 9f3d843

4 files changed

Lines changed: 42 additions & 11 deletions

File tree

ā€Žbackend/services/remote_mcp_service.pyā€Ž

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,8 @@
44
import asyncio
55
import socket
66
import random
7-
87
from fastmcp import Client
98
from fastmcp.client.transports import StreamableHttpTransport, SSETransport
10-
119
from consts.const import CAN_EDIT_ALL_USER_ROLES, PERMISSION_EDIT, PERMISSION_READ, NEXENT_MCP_DOCKER_IMAGE
1210
from consts.exceptions import (
1311
MCPConnectionError,
@@ -38,7 +36,7 @@
3836
)
3937
from database.user_tenant_db import get_user_tenant_by_user_id
4038
from services.mcp_container_service import MCPContainerManager
41-
from services.tool_configuration_service import get_tool_from_remote_mcp_server
39+
from utils.http_client_utils import create_httpx_client
4240

4341
logger = logging.getLogger("remote_mcp_service")
4442

@@ -58,11 +56,24 @@ async def mcp_server_health(remote_mcp_server: str, authorization_token: str | N
5856
headers.update(custom_headers)
5957

6058
if url_stripped.endswith("/sse"):
61-
transport = SSETransport(url=url_stripped, headers=headers)
59+
transport = SSETransport(
60+
url=url_stripped,
61+
headers=headers,
62+
httpx_client_factory=create_httpx_client
63+
)
6264
elif url_stripped.endswith("/mcp"):
63-
transport = StreamableHttpTransport(url=url_stripped, headers=headers)
65+
transport = StreamableHttpTransport(
66+
url=url_stripped,
67+
headers=headers,
68+
httpx_client_factory=create_httpx_client
69+
)
6470
else:
65-
transport = StreamableHttpTransport(url=url_stripped, headers=headers)
71+
# Default to StreamableHttpTransport for unrecognized formats
72+
transport = StreamableHttpTransport(
73+
url=url_stripped,
74+
headers=headers,
75+
httpx_client_factory=create_httpx_client
76+
)
6677

6778
client = Client(transport=transport)
6879
async with client:
@@ -1024,6 +1035,7 @@ async def list_mcp_service_tools_by_id(*, tenant_id: str, mcp_id: int) -> list[d
10241035
authorization_token = record.get("authorization_token")
10251036
custom_headers = record.get("custom_headers")
10261037

1038+
from services.tool_configuration_service import get_tool_from_remote_mcp_server
10271039
tools_info = await get_tool_from_remote_mcp_server(
10281040
mcp_server_name=service_name,
10291041
remote_mcp_server=server_url,

ā€Žbackend/services/tool_configuration_service.pyā€Ž

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
from mcpadapt.smolagents_adapter import _sanitize_function_name
3939
from services.file_management_service import get_llm_model, validate_urls_access
4040
from services.vectordatabase_service import get_embedding_model_by_index_name, get_rerank_model
41+
from utils.http_client_utils import create_httpx_client
4142
from database.client import minio_client
4243
from services.image_service import get_video_understanding_model, get_vlm_model
4344
from nexent.monitor import set_monitoring_context, set_monitoring_operation
@@ -68,12 +69,12 @@ def _create_mcp_transport(url: str, authorization_token: Optional[str] = None, c
6869
headers.update(custom_headers)
6970

7071
if url_stripped.endswith("/sse"):
71-
return SSETransport(url=url_stripped, headers=headers)
72+
return SSETransport(url=url_stripped, headers=headers, httpx_client_factory=create_httpx_client)
7273
elif url_stripped.endswith("/mcp"):
73-
return StreamableHttpTransport(url=url_stripped, headers=headers)
74+
return StreamableHttpTransport(url=url_stripped, headers=headers, httpx_client_factory=create_httpx_client)
7475
else:
7576
# Default to StreamableHttpTransport for unrecognized formats
76-
return StreamableHttpTransport(url=url_stripped, headers=headers)
77+
return StreamableHttpTransport(url=url_stripped, headers=headers, httpx_client_factory=create_httpx_client)
7778

7879

7980
def python_type_to_json_schema(annotation: Any) -> str:
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
"""HTTP client factory utilities shared across services."""
2+
3+
import httpx
4+
from httpx import AsyncClient
5+
6+
7+
def create_httpx_client(
8+
headers: dict[str, str] | None = None,
9+
timeout: httpx.Timeout | None = None,
10+
auth: httpx.Auth | None = None,
11+
) -> AsyncClient:
12+
return AsyncClient(
13+
headers=headers,
14+
timeout=timeout,
15+
auth=auth,
16+
trust_env=False,
17+
verify=False,
18+
)

ā€Žtest/backend/services/test_remote_mcp_service.pyā€Ž

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -775,7 +775,7 @@ async def test_health_without_custom_headers(self, mock_get, mock_health, mock_s
775775
class TestListMcpServiceToolsByIdCustomHeaders(unittest.IsolatedAsyncioTestCase):
776776
"""Test list_mcp_service_tools_by_id uses custom_headers from record."""
777777

778-
@patch('backend.services.remote_mcp_service.get_tool_from_remote_mcp_server')
778+
@patch('services.tool_configuration_service.get_tool_from_remote_mcp_server')
779779
@patch('backend.services.remote_mcp_service.get_mcp_record_by_id_and_tenant')
780780
async def test_tools_with_custom_headers(self, mock_get, mock_get_tools):
781781
"""Test list_mcp_service_tools_by_id passes custom_headers to tool retrieval."""
@@ -800,7 +800,7 @@ async def test_tools_with_custom_headers(self, mock_get, mock_get_tools):
800800
custom_headers={"X-Tools-Custom": "tools-value"},
801801
)
802802

803-
@patch('backend.services.remote_mcp_service.get_tool_from_remote_mcp_server')
803+
@patch('services.tool_configuration_service.get_tool_from_remote_mcp_server')
804804
@patch('backend.services.remote_mcp_service.get_mcp_record_by_id_and_tenant')
805805
async def test_tools_without_custom_headers(self, mock_get, mock_get_tools):
806806
"""Test list_mcp_service_tools_by_id when custom_headers is None."""

0 commit comments

Comments
Ā (0)