new option for mcp servers
This patch adds an option to be able to pass a `verify` option to MCP servers definition. It is set to true by default which means that TLS certificate are being checked like they were before the patch if unset. If set to `false` then the TLS certificate are not checked. This option is really useful to have agent zero work with MCP servers on internal network where it is difficult to have public and valid certificate. It will be necessary to update the MCP python module to get access to the option allowing to pass custom HTTP client.
Eric Leblond committed
Aug 21, 2025 at 15:53 UTC
f32cc92999a9ff3d34c58a40ddb3dd464a820c95
1 file changed
+38
python/helpers/mcp_handler.py
+38
@@ -24,6 +24,8 @@ import json
24
from python.helpers import errors
25
from python.helpers import settings
26
27
+import httpx
28
+
29
from mcp import ClientSession, StdioServerParameters
30
from mcp.client.stdio import stdio_client
31
from mcp.client.sse import sse_client
@@ -216,6 +218,7 @@ class MCPServerRemote(BaseModel):
218
headers: dict[str, Any] | None = Field(default_factory=dict[str, Any])
219
init_timeout: int = Field(default=0)
220
tool_timeout: int = Field(default=0)
221
+ verify: bool = Field(default=True, description="Verify SSL certificates")
222
disabled: bool = Field(default=False)
223
224
__lock: ClassVar[threading.Lock] = PrivateAttr(default=threading.Lock())
@@ -265,6 +268,7 @@ class MCPServerRemote(BaseModel):
268
"init_timeout",
269
"tool_timeout",
270
"disabled",
271
+ "verify",
272
]:
273
if key == "name":
274
value = normalize_name(value)
@@ -293,6 +297,7 @@ class MCPServerLocal(BaseModel):
297
)
298
init_timeout: int = Field(default=0)
299
tool_timeout: int = Field(default=0)
300
+ verify: bool = Field(default=True, description="Verify SSL certificates")
301
disabled: bool = Field(default=False)
302
303
__lock: ClassVar[threading.Lock] = PrivateAttr(default=threading.Lock())
@@ -1018,6 +1023,36 @@ class MCPClientLocal(MCPClientBase):
1023
# do not read or close the file here, as stdio is async
1024
return stdio_transport
1025
1026
+class CustomHTTPClientFactory(ABC):
1027
+ def __init__(self, verify: bool = True):
1028
+ self.verify = verify
1029
+
1030
+ def __call__(
1031
+ self,
1032
+ headers: dict[str, str] | None = None,
1033
+ timeout: httpx.Timeout | None = None,
1034
+ auth: httpx.Auth | None = None,
1035
+ ) -> httpx.AsyncClient:
1036
+ # Set MCP defaults
1037
+ kwargs: dict[str, Any] = {
1038
+ "follow_redirects": True,
1039
+ }
1040
+
1041
+ # Handle timeout
1042
+ if timeout is None:
1043
+ kwargs["timeout"] = httpx.Timeout(30.0)
1044
+ else:
1045
+ kwargs["timeout"] = timeout
1046
+
1047
+ # Handle headers
1048
+ if headers is not None:
1049
+ kwargs["headers"] = headers
1050
+
1051
+ # Handle authentication
1052
+ if auth is not None:
1053
+ kwargs["auth"] = auth
1054
+
1055
+ return httpx.AsyncClient(**kwargs, verify=self.verify)
1056
1057
class MCPClientRemote(MCPClientBase):
1058
@@ -1040,6 +1075,7 @@ class MCPClientRemote(MCPClientBase):
1075
init_timeout = min(server.init_timeout or set["mcp_client_init_timeout"], 5)
1076
tool_timeout = min(server.tool_timeout or set["mcp_client_tool_timeout"], 10)
1077
1078
+ client_factory = CustomHTTPClientFactory(verify=server.verify)
1079
# Check if this is a streaming HTTP type
1080
if _is_streaming_http_type(server.type):
1081
# Use streamable HTTP client
@@ -1049,6 +1085,7 @@ class MCPClientRemote(MCPClientBase):
1085
headers=server.headers,
1086
timeout=timedelta(seconds=init_timeout),
1087
sse_read_timeout=timedelta(seconds=tool_timeout),
1088
+ httpx_client_factory=client_factory,
1089
)
1090
)
1091
# streamablehttp_client returns (read_stream, write_stream, get_session_id_callback)
@@ -1066,6 +1103,7 @@ class MCPClientRemote(MCPClientBase):
1103
headers=server.headers,
1104
timeout=init_timeout,
1105
sse_read_timeout=tool_timeout,
1106
+ httpx_client_factory=client_factory,
1107
)
1108
)
1109
return stdio_transport