Skip to content

feat: Add SSL verification option to MCP tools and clients#10269

Merged
carlosrcoelho merged 37 commits into
mainfrom
add-ssl-verify-toggle-mcp
Oct 22, 2025
Merged

feat: Add SSL verification option to MCP tools and clients#10269
carlosrcoelho merged 37 commits into
mainfrom
add-ssl-verify-toggle-mcp

Conversation

@edwinjosechittilappilly
Copy link
Copy Markdown
Collaborator

@edwinjosechittilappilly edwinjosechittilappilly commented Oct 14, 2025

@coderabbitai

Summary by CodeRabbit

  • New Features

    • Added an SSL verification toggle to MCP Tools in the Nvidia Remix starter project. It’s exposed in the UI, defaults to enabled, and applies to HTTP/SSE connections.
  • Improvements

    • The SSL setting is preserved across loads and updates, ensuring consistent behavior without breaking existing setups.
  • Tests

    • Expanded automated tests to validate SSL verification behavior across clients, connections, and tool updates.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Oct 14, 2025

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Adds a configurable SSL verification flag (verify_ssl) across MCP tooling: new BoolInput in MCPToolsComponent, propagation into server configs, updates to MCPStreamableHttpClient connection methods and session factories to use SSL-aware httpx clients, starter project JSON updated accordingly, and unit tests added to validate propagation and defaults.

Changes

Cohort / File(s) Summary
MCP HTTP client and sessions
src/lfx/src/lfx/base/mcp/util.py
Adds create_mcp_http_client_with_ssl_option; threads verify_ssl through MCPStreamableHttpClient connect methods, connection params, and session creation (streamable HTTP/SSE) via httpx_client_factory; updates update_tools usage to pass verify_ssl from server_config.
Component/UI configuration
src/lfx/src/lfx/components/agents/mcp_component.py
Exposes verify_ssl as BoolInput; includes in default_keys; ensures server_config carries verify_ssl in update_tool_list, defaulting to component value.
Starter project metadata
src/backend/base/langflow/initial_setup/starter_projects/Nvidia Remix.json
Adds verify_ssl to MCPTools node inputs and default_keys; updates code_hash entries; ensures server config defaults verify_ssl from component when missing.
Unit tests
src/backend/tests/unit/base/mcp/test_mcp_util.py
Introduces tests for SSL verification behavior across client creation, connection, update_tools, and defaults; covers headers, timeout, auth, and propagation in Streamable HTTP/SSE flows.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant UI as MCPToolsComponent
  participant Cfg as server_config
  participant Cli as MCPStreamableHttpClient
  participant Util as create_mcp_http_client_with_ssl_option
  participant Net as httpx.AsyncClient

  UI->>Cfg: update_tool_list() ensures verify_ssl present
  UI->>Cli: connect_to_server(url, headers, sse_read_timeout, verify_ssl)
  Note over Cli: Store verify_ssl in connection params
  alt Streamable HTTP or SSE
    Cli->>Util: create client (headers, timeout, auth, verify_ssl)
    Util-->>Cli: factory returning SSL-configured client
    Cli->>Net: open session with verify_ssl
    Net-->>Cli: session established
  end
  Cli-->>UI: tools loaded
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

size:XXL

Suggested reviewers

  • lucaseduoli
  • jordanrfrazier
  • ogabrielluiz

Pre-merge checks and finishing touches

❌ Failed checks (1 error, 2 warnings)
Check name Status Explanation Resolution
Test Coverage For New Implementations ❌ Error The PR adds extensive unit tests for the new SSL-verification logic in the MCP HTTP client utilities and follows the project’s test_*.py naming conventions, but it does not include any tests for the corresponding changes in the MCPToolsComponent (its default_keys, inputs, and update_tool_list behavior), leaving that new component functionality unverified. Add unit tests covering the MCPToolsComponent changes—specifically tests that verify the new verify_ssl input appears in default_keys, that it is exposed in inputs, and that update_tool_list correctly injects or defaults verify_ssl on the server configuration.
Test Quality And Coverage ⚠️ Warning
Excessive Mock Usage Warning ⚠️ Warning
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title succinctly and accurately summarizes the main feature of the pull request, namely adding an SSL verification toggle to both the MCP tools component and the associated HTTP clients. It clearly conveys the scope and nature of the change without extraneous details. The use of “feat” aligns with conventional commit style and helps quickly identify the enhancement in commit history.
Docstring Coverage ✅ Passed Docstring coverage is 84.00% which is sufficient. The required threshold is 80.00%.
Test File Naming And Structure ✅ Passed The new unit tests are placed correctly under src/backend/tests/unit with filenames prefixed by test_, and they use pytest’s async support and descriptive function names to cover both default (true) and toggled (false) SSL verification scenarios as well as header, timeout, and auth propagation; there are no frontend or integration tests in this PR, which aligns with the backend‐only changes.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added the enhancement New feature or request label Oct 14, 2025
@edwinjosechittilappilly edwinjosechittilappilly marked this pull request as ready for review October 14, 2025 16:14
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds SSL certificate verification as an optional feature for MCP (Model Context Protocol) tools and clients. It enables users to disable SSL verification when working with development/testing environments that use self-signed certificates while maintaining security by defaulting to enabled SSL verification.

  • Adds a new verify_ssl parameter to MCP components and HTTP clients
  • Updates MCP connection logic to respect the SSL verification setting
  • Provides comprehensive test coverage for the new SSL verification functionality

Reviewed Changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 2 comments.

File Description
src/lfx/src/lfx/components/agents/mcp_component.py Adds verify_ssl input field and passes it through server configuration
src/lfx/src/lfx/base/mcp/util.py Implements SSL verification option in HTTP clients and session management
src/backend/tests/unit/base/mcp/test_mcp_util.py Adds comprehensive test coverage for SSL verification functionality
src/backend/base/langflow/initial_setup/starter_projects/Nvidia Remix.json Updates project configuration to include the new verify_ssl field

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment on lines 716 to 718
session_id: Unique identifier for this session
connection_params: Connection parameters including URL, headers, timeouts
connection_params: Connection parameters including URL, headers, timeouts, verify_ssl
preferred_transport: If set to "sse", skip Streamable HTTP and go directly to SSE
Copy link

Copilot AI Oct 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docstring comment is incomplete and should be properly formatted. It appears to be a fragment that should be part of a structured docstring.

Copilot uses AI. Check for mistakes.
Comment on lines 1215 to +1271
# Store connection parameters for later use in run_tool
# Include SSE read timeout for fallback
# Include SSE read timeout for fallback and SSL verification option
Copy link

Copilot AI Oct 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The comment should be more descriptive and explain what the connection parameters dictionary contains, not just list the additions.

Copilot uses AI. Check for mistakes.
@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Oct 14, 2025
@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Oct 14, 2025
@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Oct 14, 2025
@github-actions
Copy link
Copy Markdown
Contributor

Component index has been automatically updated due to changes in src/lfx/src/lfx/components/

New Index:
🧩 Components: 356
📁 Categories: 91

@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Oct 14, 2025
@github-actions
Copy link
Copy Markdown
Contributor

Component index has been automatically updated due to changes in src/lfx/src/lfx/components/

New Index:
🧩 Components: 355
📁 Categories: 91

@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Oct 14, 2025
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
src/lfx/src/lfx/base/mcp/util.py (2)

1297-1310: Expose timeout_seconds on connect_to_server to avoid API regression

connect_to_server no longer exposes timeout_seconds but _connect_to_server still supports it. If callers previously set it, this change breaks that. Recommend adding it back and passing through.

@@
-    async def connect_to_server(
-        self,
-        url: str,
-        headers: dict[str, str] | None = None,
-        sse_read_timeout_seconds: int = 30,
-        verify_ssl: bool = True,
-    ) -> list[StructuredTool]:
+    async def connect_to_server(
+        self,
+        url: str,
+        headers: dict[str, str] | None = None,
+        timeout_seconds: int = 30,
+        sse_read_timeout_seconds: int = 30,
+        verify_ssl: bool = True,
+    ) -> list[StructuredTool]:
@@
-            self._connect_to_server(
-                url, headers, sse_read_timeout_seconds=sse_read_timeout_seconds, verify_ssl=verify_ssl
-            ),
+            self._connect_to_server(
+                url,
+                headers,
+                timeout_seconds=timeout_seconds,
+                sse_read_timeout_seconds=sse_read_timeout_seconds,
+                verify_ssl=verify_ssl,
+            ),

1348-1353: Use verify_ssl when sending DELETE on disconnect

_terminate_remote_session creates a fresh AsyncClient with default verify=True. For self‑signed setups (verify_ssl=False), this will consistently fail. Respect the stored verify_ssl.

-            async with httpx.AsyncClient(timeout=5.0) as client:
+            verify_ssl = self._connection_params.get("verify_ssl", True)
+            async with httpx.AsyncClient(timeout=5.0, verify=verify_ssl) as client:
                 await client.delete(url, headers=headers)
src/backend/tests/unit/base/mcp/test_mcp_util.py (1)

1627-1714: Close AsyncClient instances; make tests async and use async with

These tests construct httpx.AsyncClient but never close it, risking resource leaks and warnings. Convert to async tests and use async with (or await client.aclose()).

Example fixes:

@@
-    def test_create_mcp_http_client_with_ssl_option_default(self):
+    @pytest.mark.asyncio
+    async def test_create_mcp_http_client_with_ssl_option_default(self):
         """Test that the custom httpx client factory defaults to SSL verification enabled."""
         from lfx.base.mcp.util import create_mcp_http_client_with_ssl_option
+        import httpx
-
-        client = create_mcp_http_client_with_ssl_option()
-
-        # Verify that SSL verification is enabled by default using _transport
-        # httpx stores verify in the transport config, not as a direct attribute
-        assert client._transport is not None or client.is_closed
-        # Just verify the client was created successfully with default settings
-        assert isinstance(client, type(client))
+        async with create_mcp_http_client_with_ssl_option() as client:
+            # Sanity: client created successfully
+            assert isinstance(client, httpx.AsyncClient)
@@
-    def test_create_mcp_http_client_with_ssl_disabled(self):
+    @pytest.mark.asyncio
+    async def test_create_mcp_http_client_with_ssl_disabled(self):
         """Test creating httpx client with SSL verification disabled."""
         from lfx.base.mcp.util import create_mcp_http_client_with_ssl_option
-
-        # The key test is that this doesn't raise an exception
-        client = create_mcp_http_client_with_ssl_option(verify_ssl=False)
-
-        # Verify client was created successfully
-        assert isinstance(client, type(client))
+        import httpx
+        async with create_mcp_http_client_with_ssl_option(verify_ssl=False) as client:
+            assert isinstance(client, httpx.AsyncClient)
@@
-    def test_create_mcp_http_client_with_ssl_enabled_explicit(self):
+    @pytest.mark.asyncio
+    async def test_create_mcp_http_client_with_ssl_enabled_explicit(self):
         """Test creating httpx client with SSL verification explicitly enabled."""
         from lfx.base.mcp.util import create_mcp_http_client_with_ssl_option
-
-        client = create_mcp_http_client_with_ssl_option(verify_ssl=True)
-
-        # Verify client was created successfully
-        assert isinstance(client, type(client))
+        import httpx
+        async with create_mcp_http_client_with_ssl_option(verify_ssl=True) as client:
+            assert isinstance(client, httpx.AsyncClient)
@@
-    def test_create_mcp_http_client_with_ssl_and_headers(self):
+    @pytest.mark.asyncio
+    async def test_create_mcp_http_client_with_ssl_and_headers(self):
         """Test creating httpx client with SSL option and custom headers."""
         from lfx.base.mcp.util import create_mcp_http_client_with_ssl_option
@@
-        client = create_mcp_http_client_with_ssl_option(headers=test_headers, verify_ssl=False)
-
-        # Verify headers are set correctly
-        assert client.headers["Authorization"] == "Bearer token123"
-        assert client.headers["X-API-Key"] == "secret"
+        async with create_mcp_http_client_with_ssl_option(headers=test_headers, verify_ssl=False) as client:
+            assert client.headers["Authorization"] == "Bearer token123"
+            assert client.headers["X-API-Key"] == "secret"
@@
-    def test_create_mcp_http_client_with_ssl_and_timeout(self):
+    @pytest.mark.asyncio
+    async def test_create_mcp_http_client_with_ssl_and_timeout(self):
@@
-        client = create_mcp_http_client_with_ssl_option(timeout=custom_timeout, verify_ssl=False)
-
-        # Verify timeout is set correctly - httpx.Timeout has read attribute
-        assert client.timeout.read == 120.0
+        async with create_mcp_http_client_with_ssl_option(timeout=custom_timeout, verify_ssl=False) as client:
+            assert client.timeout.read == 120.0
@@
-    def test_create_mcp_http_client_with_ssl_and_auth(self):
+    @pytest.mark.asyncio
+    async def test_create_mcp_http_client_with_ssl_and_auth(self):
@@
-        client = create_mcp_http_client_with_ssl_option(auth=auth, verify_ssl=False)
-
-        # Verify auth is set correctly
-        assert client.auth == auth
+        async with create_mcp_http_client_with_ssl_option(auth=auth, verify_ssl=False) as client:
+            assert client.auth == auth
@@
-    def test_create_mcp_http_client_all_options(self):
+    @pytest.mark.asyncio
+    async def test_create_mcp_http_client_all_options(self):
@@
-        client = create_mcp_http_client_with_ssl_option(
-            headers=test_headers, timeout=custom_timeout, auth=auth, verify_ssl=False
-        )
-
-        # Verify all options are set correctly
-        assert client.headers["Authorization"] == "Bearer token123"
-        assert client.timeout == custom_timeout
-        assert client.auth == auth
+        async with create_mcp_http_client_with_ssl_option(
+            headers=test_headers, timeout=custom_timeout, auth=auth, verify_ssl=False
+        ) as client:
+            assert client.headers["Authorization"] == "Bearer token123"
+            assert client.timeout == custom_timeout
+            assert client.auth == auth

Based on learnings

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 354a6ce and 4b2d5be.

📒 Files selected for processing (4)
  • src/backend/base/langflow/initial_setup/starter_projects/Nvidia Remix.json (3 hunks)
  • src/backend/tests/unit/base/mcp/test_mcp_util.py (2 hunks)
  • src/lfx/src/lfx/base/mcp/util.py (9 hunks)
  • src/lfx/src/lfx/components/agents/mcp_component.py (3 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
{src/backend/**/*.py,tests/**/*.py,Makefile}

📄 CodeRabbit inference engine (.cursor/rules/backend_development.mdc)

{src/backend/**/*.py,tests/**/*.py,Makefile}: Run make format_backend to format Python code before linting or committing changes
Run make lint to perform linting checks on backend Python code

Files:

  • src/backend/tests/unit/base/mcp/test_mcp_util.py
src/backend/tests/unit/**/*.py

📄 CodeRabbit inference engine (.cursor/rules/backend_development.mdc)

Test component integration within flows using create_flow, build_flow, and get_build_events utilities

Files:

  • src/backend/tests/unit/base/mcp/test_mcp_util.py
src/backend/tests/**/*.py

📄 CodeRabbit inference engine (.cursor/rules/testing.mdc)

src/backend/tests/**/*.py: Unit tests for backend code must be located in the 'src/backend/tests/' directory, with component tests organized by component subdirectory under 'src/backend/tests/unit/components/'.
Test files should use the same filename as the component under test, with an appropriate test prefix or suffix (e.g., 'my_component.py' → 'test_my_component.py').
Use the 'client' fixture (an async httpx.AsyncClient) for API tests in backend Python tests, as defined in 'src/backend/tests/conftest.py'.
When writing component tests, inherit from the appropriate base class in 'src/backend/tests/base.py' (ComponentTestBase, ComponentTestBaseWithClient, or ComponentTestBaseWithoutClient) and provide the required fixtures: 'component_class', 'default_kwargs', and 'file_names_mapping'.
Each test in backend Python test files should have a clear docstring explaining its purpose, and complex setups or mocks should be well-commented.
Test both sync and async code paths in backend Python tests, using '@pytest.mark.asyncio' for async tests.
Mock external dependencies appropriately in backend Python tests to isolate unit tests from external services.
Test error handling and edge cases in backend Python tests, including using 'pytest.raises' and asserting error messages.
Validate input/output behavior and test component initialization and configuration in backend Python tests.
Use the 'no_blockbuster' pytest marker to skip the blockbuster plugin in tests when necessary.
Be aware of ContextVar propagation in async tests; test both direct event loop execution and 'asyncio.to_thread' scenarios to ensure proper context isolation.
Test error handling by mocking internal functions using monkeypatch in backend Python tests.
Test resource cleanup in backend Python tests by using fixtures that ensure proper initialization and cleanup of resources.
Test timeout and performance constraints in backend Python tests using 'asyncio.wait_for' and timing assertions.
Test Langflow's Messag...

Files:

  • src/backend/tests/unit/base/mcp/test_mcp_util.py
**/@(test_*.py|*.test.@(ts|tsx))

📄 CodeRabbit inference engine (coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt)

**/@(test_*.py|*.test.@(ts|tsx)): Check if tests have too many mock objects that obscure what's actually being tested
Warn when mocks are used instead of testing real behavior and interactions
Suggest using real objects or test doubles when mocks become excessive
Ensure mocks are used appropriately for external dependencies, not core logic
Recommend integration tests when unit tests become overly mocked
Test files should have descriptive test function names explaining what is tested
Tests should be organized logically with proper setup and teardown
Include edge cases and error conditions for comprehensive coverage
Verify tests cover both positive and negative scenarios where appropriate
Tests should cover the main functionality being implemented
Ensure tests are not just smoke tests but actually validate behavior
For API endpoints, verify both success and error response testing

Files:

  • src/backend/tests/unit/base/mcp/test_mcp_util.py
**/test_*.py

📄 CodeRabbit inference engine (coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt)

**/test_*.py: Check that backend test files follow naming convention: test_.py
Backend tests should be named test_
.py and follow proper pytest structure
For async Python code, ensure proper async testing patterns (pytest) are used
Backend tests should follow pytest conventions; frontend tests should use Playwright

Files:

  • src/backend/tests/unit/base/mcp/test_mcp_util.py
🧬 Code graph analysis (2)
src/lfx/src/lfx/components/agents/mcp_component.py (1)
src/lfx/src/lfx/inputs/inputs.py (1)
  • BoolInput (414-426)
src/backend/tests/unit/base/mcp/test_mcp_util.py (1)
src/lfx/src/lfx/base/mcp/util.py (6)
  • create_mcp_http_client_with_ssl_option (68-104)
  • MCPStreamableHttpClient (1213-1483)
  • connect_to_server (1048-1052)
  • connect_to_server (1296-1309)
  • MCPSessionManager (438-997)
  • update_tools (1491-1636)
🔇 Additional comments (7)
src/lfx/src/lfx/components/agents/mcp_component.py (3)

64-64: LGTM! Correct addition to default_keys.

Adding "verify_ssl" to default_keys ensures this setting persists when switching tools and isn't cleared by remove_non_default_keys(). This is consistent with other persistent settings like "use_cache".


90-99: LGTM! Well-designed SSL verification input.

The verify_ssl input is properly configured:

  • Secure by default (value=True)
  • Clear documentation warning users to disable only for development/testing
  • Appropriately marked as advanced
  • Follows the same pattern as the use_cache input above

224-227: verify_ssl is consumed in the HTTP client factory
The verify_ssl flag flows from server_config into create_mcp_http_client_with_ssl_option, where it sets the HTTPX client's verify option.

src/lfx/src/lfx/base/mcp/util.py (2)

68-105: httpx client factory with SSL toggle looks good

Uses httpx verify flag correctly; sane defaults and options. No issues.

Based on learnings


1538-1540: verify_ssl propagation into update_tools is correct

verify_ssl read from server_config and passed to client. Looks good.

src/backend/tests/unit/base/mcp/test_mcp_util.py (2)

1750-1772: Assert verify_ssl persistence is good; no issues

These cover False/True paths and ensure connection params carry verify_ssl. Looks good.

Also applies to: 1774-1804


1834-1912: update_tools verify_ssl propagation test is valid

Captures verify_ssl argument; also tests default True. Solid coverage.

Comment on lines +733 to +745
# Get verify_ssl option from connection params, default to True
verify_ssl = connection_params.get("verify_ssl", True)

# Create custom httpx client factory with SSL verification option
def custom_httpx_factory(
headers: dict[str, str] | None = None,
timeout: httpx.Timeout | None = None,
auth: httpx.Auth | None = None,
) -> httpx.AsyncClient:
return create_mcp_http_client_with_ssl_option(
headers=headers, timeout=timeout, auth=auth, verify_ssl=verify_ssl
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Honor verify_ssl across session reuse (include in server key)

You pass verify_ssl to the httpx factory (great), but MCPSessionManager’s streamable_http server key doesn’t include verify_ssl. A session created with verify_ssl=False can be reused when verify_ssl=True is requested, silently weakening TLS guarantees. Include verify_ssl in the server key to prevent insecure reuse.

Apply:

@@
-        elif transport_type == "streamable_http" and (
-            isinstance(connection_params, dict) and "url" in connection_params
-        ):
-            # Include URL and headers for uniqueness
-            url = connection_params["url"]
-            headers = str(sorted((connection_params.get("headers", {})).items()))
-            key_input = f"{url}|{headers}"
-            return f"streamable_http_{hash(key_input)}"
+        elif transport_type == "streamable_http" and (
+            isinstance(connection_params, dict) and "url" in connection_params
+        ):
+            # Include URL, headers, and SSL verify for uniqueness
+            url = connection_params["url"]
+            headers = str(sorted((connection_params.get("headers", {})).items()))
+            verify_ssl = connection_params.get("verify_ssl", True)
+            key_input = f"{url}|{headers}|verify_ssl={verify_ssl}"
+            return f"streamable_http_{hash(key_input)}"

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/lfx/src/lfx/base/mcp/util.py around lines 733 to 745, the verify_ssl flag
is passed into the custom_httpx_factory but is not included in the
MCPSessionManager’s streamable_http server key; this can allow a session created
with verify_ssl=False to be reused for verify_ssl=True. Fix by adding the
normalized verify_ssl value (e.g., bool(verify_ssl)) to the server key
construction where streamable_http keys are built (include it in the tuple/dict
that identifies the server), and ensure any lookup or storage of sessions uses
this augmented key so sessions with different verify_ssl settings are not mixed.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
src/lfx/src/lfx/base/mcp/util.py (3)

518-525: Include verify_ssl in the server key for streamable HTTP sessions

Currently, sessions are keyed by URL+headers only. Reusing a session created with verify_ssl=False when a caller requests verify_ssl=True (or vice‑versa) can cause confusing behavior and weakens the isolation of TLS settings.

-            # Include URL and headers for uniqueness
+            # Include URL, headers and TLS verification mode for uniqueness
             url = connection_params["url"]
             headers = str(sorted((connection_params.get("headers", {})).items()))
-            key_input = f"{url}|{headers}"
+            verify = connection_params.get("verify_ssl", True)
+            key_input = f"{url}|{headers}|verify={verify}"
             return f"streamable_http_{hash(key_input)}"

1269-1281: Persist verify_ssl changes on subsequent connects

When reconnecting with different verify_ssl, the value isn’t updated if _connection_params already exist. This can lead to stale settings.

-            # Store connection parameters for later use in run_tool
-            # Include SSE read timeout for fallback and SSL verification option
+            # Store connection parameters for later use in run_tool
+            # Include SSE read timeout for fallback and SSL verification option
             self._connection_params = {
                 "url": url,
                 "headers": validated_headers,
                 "timeout_seconds": timeout_seconds,
                 "sse_read_timeout_seconds": sse_read_timeout_seconds,
                 "verify_ssl": verify_ssl,
             }
-        elif headers:
-            self._connection_params["headers"] = validated_headers
+        else:
+            if headers is not None:
+                self._connection_params["headers"] = validated_headers
+            # Always refresh verify_ssl to reflect caller intent
+            self._connection_params["verify_ssl"] = verify_ssl

1348-1352: Honor verify_ssl during remote session termination

The best‑effort DELETE uses a default httpx.AsyncClient with verification enabled, which will fail against self‑signed endpoints when the connection was established with verify_ssl=False.

-        try:
-            async with httpx.AsyncClient(timeout=5.0) as client:
-                await client.delete(url, headers=headers)
+        try:
+            verify = bool(self._connection_params.get("verify_ssl", True))
+            async with create_mcp_http_client_with_ssl_option(timeout=httpx.Timeout(5.0), verify_ssl=verify) as client:
+                await client.delete(url, headers=headers)
🧹 Nitpick comments (2)
src/backend/tests/unit/base/mcp/test_mcp_util.py (1)

1630-1660: Optional: close AsyncClient instances in tests to avoid resource warnings

These tests create httpx.AsyncClient instances but never close them. Consider making them async and using async with for clean teardown.

-    def test_create_mcp_http_client_with_ssl_option_default(self):
+    @pytest.mark.asyncio
+    async def test_create_mcp_http_client_with_ssl_option_default(self):
         """Test that the custom httpx client factory defaults to SSL verification enabled."""
-        from lfx.base.mcp.util import create_mcp_http_client_with_ssl_option
-
-        client = create_mcp_http_client_with_ssl_option()
-
-        # Verify that SSL verification is enabled by default using _transport
-        # httpx stores verify in the transport config, not as a direct attribute
-        assert client._transport is not None or client.is_closed
-        # Just verify the client was created successfully with default settings
-        assert isinstance(client, type(client))
+        import httpx
+        from lfx.base.mcp.util import create_mcp_http_client_with_ssl_option
+        async with create_mcp_http_client_with_ssl_option() as client:
+            assert isinstance(client, httpx.AsyncClient)

Apply the same pattern to the other create_mcp_http_client_* tests for consistency.

src/lfx/src/lfx/base/mcp/util.py (1)

1296-1309: Optional: expose timeout_seconds in connect_to_server for parity

Public connect_to_server no longer accepts timeout_seconds. Consider adding it back (keyword‑only) to let callers tune initial connection timeouts without relying solely on global settings.

Example:

-    async def connect_to_server(
-        self,
-        url: str,
-        headers: dict[str, str] | None = None,
-        sse_read_timeout_seconds: int = 30,
-        verify_ssl: bool = True,
-    ) -> list[StructuredTool]:
+    async def connect_to_server(
+        self,
+        url: str,
+        headers: dict[str, str] | None = None,
+        *,
+        timeout_seconds: int = 30,
+        sse_read_timeout_seconds: int = 30,
+        verify_ssl: bool = True,
+    ) -> list[StructuredTool]:
         """Connect to MCP server using Streamable HTTP with SSE fallback transport (SDK style)."""
         return await asyncio.wait_for(
-            self._connect_to_server(
-                url, headers, sse_read_timeout_seconds=sse_read_timeout_seconds, verify_ssl=verify_ssl
-            ),
+            self._connect_to_server(
+                url,
+                headers,
+                timeout_seconds=timeout_seconds,
+                sse_read_timeout_seconds=sse_read_timeout_seconds,
+                verify_ssl=verify_ssl,
+            ),
             timeout=get_settings_service().settings.mcp_server_timeout,
         )
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 354a6ce and 1aab7d1.

📒 Files selected for processing (4)
  • src/backend/base/langflow/initial_setup/starter_projects/Nvidia Remix.json (3 hunks)
  • src/backend/tests/unit/base/mcp/test_mcp_util.py (2 hunks)
  • src/lfx/src/lfx/base/mcp/util.py (9 hunks)
  • src/lfx/src/lfx/components/agents/mcp_component.py (3 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
{src/backend/**/*.py,tests/**/*.py,Makefile}

📄 CodeRabbit inference engine (.cursor/rules/backend_development.mdc)

{src/backend/**/*.py,tests/**/*.py,Makefile}: Run make format_backend to format Python code before linting or committing changes
Run make lint to perform linting checks on backend Python code

Files:

  • src/backend/tests/unit/base/mcp/test_mcp_util.py
src/backend/tests/unit/**/*.py

📄 CodeRabbit inference engine (.cursor/rules/backend_development.mdc)

Test component integration within flows using create_flow, build_flow, and get_build_events utilities

Files:

  • src/backend/tests/unit/base/mcp/test_mcp_util.py
src/backend/tests/**/*.py

📄 CodeRabbit inference engine (.cursor/rules/testing.mdc)

src/backend/tests/**/*.py: Unit tests for backend code must be located in the 'src/backend/tests/' directory, with component tests organized by component subdirectory under 'src/backend/tests/unit/components/'.
Test files should use the same filename as the component under test, with an appropriate test prefix or suffix (e.g., 'my_component.py' → 'test_my_component.py').
Use the 'client' fixture (an async httpx.AsyncClient) for API tests in backend Python tests, as defined in 'src/backend/tests/conftest.py'.
When writing component tests, inherit from the appropriate base class in 'src/backend/tests/base.py' (ComponentTestBase, ComponentTestBaseWithClient, or ComponentTestBaseWithoutClient) and provide the required fixtures: 'component_class', 'default_kwargs', and 'file_names_mapping'.
Each test in backend Python test files should have a clear docstring explaining its purpose, and complex setups or mocks should be well-commented.
Test both sync and async code paths in backend Python tests, using '@pytest.mark.asyncio' for async tests.
Mock external dependencies appropriately in backend Python tests to isolate unit tests from external services.
Test error handling and edge cases in backend Python tests, including using 'pytest.raises' and asserting error messages.
Validate input/output behavior and test component initialization and configuration in backend Python tests.
Use the 'no_blockbuster' pytest marker to skip the blockbuster plugin in tests when necessary.
Be aware of ContextVar propagation in async tests; test both direct event loop execution and 'asyncio.to_thread' scenarios to ensure proper context isolation.
Test error handling by mocking internal functions using monkeypatch in backend Python tests.
Test resource cleanup in backend Python tests by using fixtures that ensure proper initialization and cleanup of resources.
Test timeout and performance constraints in backend Python tests using 'asyncio.wait_for' and timing assertions.
Test Langflow's Messag...

Files:

  • src/backend/tests/unit/base/mcp/test_mcp_util.py
**/@(test_*.py|*.test.@(ts|tsx))

📄 CodeRabbit inference engine (coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt)

**/@(test_*.py|*.test.@(ts|tsx)): Check if tests have too many mock objects that obscure what's actually being tested
Warn when mocks are used instead of testing real behavior and interactions
Suggest using real objects or test doubles when mocks become excessive
Ensure mocks are used appropriately for external dependencies, not core logic
Recommend integration tests when unit tests become overly mocked
Test files should have descriptive test function names explaining what is tested
Tests should be organized logically with proper setup and teardown
Include edge cases and error conditions for comprehensive coverage
Verify tests cover both positive and negative scenarios where appropriate
Tests should cover the main functionality being implemented
Ensure tests are not just smoke tests but actually validate behavior
For API endpoints, verify both success and error response testing

Files:

  • src/backend/tests/unit/base/mcp/test_mcp_util.py
**/test_*.py

📄 CodeRabbit inference engine (coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt)

**/test_*.py: Check that backend test files follow naming convention: test_.py
Backend tests should be named test_
.py and follow proper pytest structure
For async Python code, ensure proper async testing patterns (pytest) are used
Backend tests should follow pytest conventions; frontend tests should use Playwright

Files:

  • src/backend/tests/unit/base/mcp/test_mcp_util.py
🧬 Code graph analysis (2)
src/lfx/src/lfx/components/agents/mcp_component.py (1)
src/lfx/src/lfx/inputs/inputs.py (1)
  • BoolInput (414-426)
src/backend/tests/unit/base/mcp/test_mcp_util.py (3)
src/lfx/src/lfx/base/mcp/util.py (7)
  • create_mcp_http_client_with_ssl_option (68-104)
  • MCPStreamableHttpClient (1213-1483)
  • connect_to_server (1048-1052)
  • connect_to_server (1296-1309)
  • MCPSessionManager (438-997)
  • cleanup_all (935-972)
  • update_tools (1491-1636)
src/backend/tests/unit/components/agents/test_mcp_component_cache.py (1)
  • mock_tool (41-49)
src/backend/tests/integration/components/mcp/test_mcp_memory_leak.py (2)
  • list_tools (334-343)
  • list_tools (357-358)
🪛 GitHub Actions: Ruff Style Check
src/backend/tests/unit/base/mcp/test_mcp_util.py

[error] 423-423: Ruff check failed: I001 Import block is un-sorted or un-formatted.

🪛 GitHub Check: Ruff Style Check (3.13)
src/backend/tests/unit/base/mcp/test_mcp_util.py

[failure] 1888-1888: Ruff (ARG001)
src/backend/tests/unit/base/mcp/test_mcp_util.py:1888:37: ARG001 Unused function argument: headers


[failure] 1888-1888: Ruff (ARG001)
src/backend/tests/unit/base/mcp/test_mcp_util.py:1888:32: ARG001 Unused function argument: url


[failure] 1869-1871: Ruff (S110)
src/backend/tests/unit/base/mcp/test_mcp_util.py:1869:9: S110 try-except-pass detected, consider logging the exception


[failure] 1863-1871: Ruff (SIM105)
src/backend/tests/unit/base/mcp/test_mcp_util.py:1863:9: SIM105 Use contextlib.suppress(Exception) instead of try-except-pass


[failure] 1845-1845: Ruff (FBT002)
src/backend/tests/unit/base/mcp/test_mcp_util.py:1845:80: FBT002 Boolean default positional argument in function definition


[failure] 1845-1845: Ruff (ARG001)
src/backend/tests/unit/base/mcp/test_mcp_util.py:1845:51: ARG001 Unused function argument: sse_read_timeout_seconds


[failure] 1842-1842: Ruff (F841)
src/backend/tests/unit/base/mcp/test_mcp_util.py:1842:9: F841 Local variable original_connect is assigned to but never used


[failure] 1704-1704: Ruff (S106)
src/backend/tests/unit/base/mcp/test_mcp_util.py:1704:53: S106 Possible hardcoded password assigned to argument: "password"


[failure] 1690-1690: Ruff (S106)
src/backend/tests/unit/base/mcp/test_mcp_util.py:1690:49: S106 Possible hardcoded password assigned to argument: "password"

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (16)
  • GitHub Check: Lint Backend / Run Mypy (3.11)
  • GitHub Check: Run Frontend Tests / Determine Test Suites and Shard Distribution
  • GitHub Check: Lint Backend / Run Mypy (3.10)
  • GitHub Check: Lint Backend / Run Mypy (3.12)
  • GitHub Check: Lint Backend / Run Mypy (3.13)
  • GitHub Check: Run Backend Tests / Unit Tests - Python 3.10 - Group 3
  • GitHub Check: Run Backend Tests / Unit Tests - Python 3.10 - Group 4
  • GitHub Check: Run Backend Tests / Unit Tests - Python 3.10 - Group 5
  • GitHub Check: Run Backend Tests / Unit Tests - Python 3.10 - Group 2
  • GitHub Check: Run Backend Tests / Unit Tests - Python 3.10 - Group 1
  • GitHub Check: Run Backend Tests / Integration Tests - Python 3.10
  • GitHub Check: Test Starter Templates
  • GitHub Check: Optimize new Python code in this PR
  • GitHub Check: Update Starter Projects
  • GitHub Check: test-starter-projects
  • GitHub Check: update-index
🔇 Additional comments (3)
src/lfx/src/lfx/base/mcp/util.py (3)

68-105: Factory for SSL‑configurable AsyncClient looks good

Uses httpx verify correctly, sets sensible defaults, and cleanly passes headers/auth/timeout.

If httpx version varies across environments, confirm verify still accepts a bool as in 0.28.x (Based on learnings).


710-745: Good integration: factory wired into session creation and respects verify_ssl

Pulling verify_ssl from connection_params and injecting via httpx_client_factory is clean and extensible.


1537-1540: update_tools correctly propagates verify_ssl

Reading verify_ssl from server_config with default True and passing to the client aligns with the new option.

Comment on lines 424 to 427

from pydantic import ValidationError

# Create a JSON schema with snake_case field names
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Fix import block ordering to satisfy Ruff I001

Within the function, group/sort imports correctly (third‑party before first‑party) and remove the blank line.

-        from lfx.schema.json_schema import create_input_schema_from_json_schema
-
-        from pydantic import ValidationError
+        from pydantic import ValidationError
+        from lfx.schema.json_schema import create_input_schema_from_json_schema
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
from lfx.schema.json_schema import create_input_schema_from_json_schema
from pydantic import ValidationError
from pydantic import ValidationError
from lfx.schema.json_schema import create_input_schema_from_json_schema
🧰 Tools
🪛 GitHub Actions: Ruff Style Check

[error] 423-423: Ruff check failed: I001 Import block is un-sorted or un-formatted.

🪛 GitHub Check: Ruff Style Check (3.13)

[failure] 423-425: Ruff (I001)
src/backend/tests/unit/base/mcp/test_mcp_util.py:423:9: I001 Import block is un-sorted or un-formatted

🤖 Prompt for AI Agents
In src/backend/tests/unit/base/mcp/test_mcp_util.py around lines 423 to 426, the
in-function import block currently has a blank line and places the first‑party
import before a third‑party import; reorder the imports so third‑party imports
(e.g., from pydantic import ValidationError) come before first‑party imports
(e.g., from lfx.schema.json_schema import create_input_schema_from_json_schema),
remove the extraneous blank line, and ensure the imports are grouped and sorted
to satisfy Ruff I001.

Comment on lines +1692 to +1693
client = create_mcp_http_client_with_ssl_option(auth=auth, verify_ssl=False)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Silence hardcoded password warnings in tests (S106)

These are benign in unit tests. Add noqa to avoid failing the style check.

-        auth = httpx.BasicAuth(username="user", password="pass")
+        auth = httpx.BasicAuth(username="user", password="pass")  # noqa: S106
-        auth = httpx.BasicAuth(username="testuser", password="testpass")
+        auth = httpx.BasicAuth(username="testuser", password="testpass")  # noqa: S106

Also applies to: 1704-1705

🧰 Tools
🪛 GitHub Check: Ruff Style Check (3.13)

[failure] 1690-1690: Ruff (S106)
src/backend/tests/unit/base/mcp/test_mcp_util.py:1690:49: S106 Possible hardcoded password assigned to argument: "password"

🤖 Prompt for AI Agents
In src/backend/tests/unit/base/mcp/test_mcp_util.py around lines 1690-1691 (and
also lines 1704-1705), the test uses hardcoded credentials which trigger the
S106 style check; silence these benign test warnings by appending a noqa S106
directive to those lines (e.g., add "# noqa: S106" at the end of the BasicAuth
assignment lines) so the linter ignores the hardcoded password in tests.

Comment on lines +1844 to +1855

async def mock_connect(url, headers=None, sse_read_timeout_seconds=30, verify_ssl=True):
connect_called_with["url"] = url
connect_called_with["headers"] = headers
connect_called_with["verify_ssl"] = verify_ssl
# Return empty tool list
return []

mock_client.connect_to_server = mock_connect
mock_client._connected = False

# Test server config with verify_ssl=False
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Remove unused variable and fix boolean-trap/unused-args in mock connect_to_server

  • Remove original_connect (F841).
  • Make verify_ssl keyword‑only (FBT002).
  • Prefix unused parameters with _ to silence ARG001.
-        original_connect = mock_client.connect_to_server
         connect_called_with = {}
 
-        async def mock_connect(url, headers=None, sse_read_timeout_seconds=30, verify_ssl=True):
-            connect_called_with["url"] = url
-            connect_called_with["headers"] = headers
-            connect_called_with["verify_ssl"] = verify_ssl
-            # Return empty tool list
-            return []
+        async def mock_connect(_url, _headers=None, *, _sse_read_timeout_seconds=30, verify_ssl: bool = True):
+            connect_called_with["verify_ssl"] = verify_ssl
+            return []
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
original_connect = mock_client.connect_to_server
connect_called_with = {}
async def mock_connect(url, headers=None, sse_read_timeout_seconds=30, verify_ssl=True):
connect_called_with["url"] = url
connect_called_with["headers"] = headers
connect_called_with["verify_ssl"] = verify_ssl
# Return empty tool list
return []
mock_client.connect_to_server = mock_connect
mock_client._connected = False
connect_called_with = {}
async def mock_connect(_url, _headers=None, *, _sse_read_timeout_seconds=30, verify_ssl: bool = True):
connect_called_with["verify_ssl"] = verify_ssl
return []
mock_client.connect_to_server = mock_connect
mock_client._connected = False
🧰 Tools
🪛 GitHub Check: Ruff Style Check (3.13)

[failure] 1845-1845: Ruff (FBT002)
src/backend/tests/unit/base/mcp/test_mcp_util.py:1845:80: FBT002 Boolean default positional argument in function definition


[failure] 1845-1845: Ruff (ARG001)
src/backend/tests/unit/base/mcp/test_mcp_util.py:1845:51: ARG001 Unused function argument: sse_read_timeout_seconds


[failure] 1842-1842: Ruff (F841)
src/backend/tests/unit/base/mcp/test_mcp_util.py:1842:9: F841 Local variable original_connect is assigned to but never used

🤖 Prompt for AI Agents
In src/backend/tests/unit/base/mcp/test_mcp_util.py around lines 1842-1853,
remove the unused variable original_connect, and update the mock_connect
signature to make verify_ssl keyword-only and silence unused-arg warnings by
prefixing unused parameters with underscores; e.g., change parameters to url, *,
_headers=None, _sse_read_timeout_seconds=30, verify_ssl=True (or equivalent) and
update any uses that record those values (connect_called_with["headers"] =
_headers, etc.).

Comment on lines +1865 to +1873
server_name="test_server",
server_config=server_config,
mcp_streamable_http_client=mock_client,
)
except Exception:
# May fail due to incomplete mocking, but we can still check if connect was called correctly
pass

# Verify that connect_to_server was called with verify_ssl=False
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Replace try/except/pass with contextlib.suppress and avoid swallowing silently

Use contextlib.suppress to satisfy SIM105/S110 while keeping the test intent.

-        try:
-            await update_tools(
-                server_name="test_server",
-                server_config=server_config,
-                mcp_streamable_http_client=mock_client,
-            )
-        except Exception:
-            # May fail due to incomplete mocking, but we can still check if connect was called correctly
-            pass
+        import contextlib
+        with contextlib.suppress(Exception):
+            await update_tools(
+                server_name="test_server",
+                server_config=server_config,
+                mcp_streamable_http_client=mock_client,
+            )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
try:
await update_tools(
server_name="test_server",
server_config=server_config,
mcp_streamable_http_client=mock_client,
)
except Exception:
# May fail due to incomplete mocking, but we can still check if connect was called correctly
pass
import contextlib
with contextlib.suppress(Exception):
await update_tools(
server_name="test_server",
server_config=server_config,
mcp_streamable_http_client=mock_client,
)
🧰 Tools
🪛 GitHub Check: Ruff Style Check (3.13)

[failure] 1869-1871: Ruff (S110)
src/backend/tests/unit/base/mcp/test_mcp_util.py:1869:9: S110 try-except-pass detected, consider logging the exception


[failure] 1863-1871: Ruff (SIM105)
src/backend/tests/unit/base/mcp/test_mcp_util.py:1863:9: SIM105 Use contextlib.suppress(Exception) instead of try-except-pass

🤖 Prompt for AI Agents
In src/backend/tests/unit/base/mcp/test_mcp_util.py around lines 1863 to 1871,
replace the try/except/pass that swallows all exceptions with
contextlib.suppress to satisfy linters: import contextlib (or from contextlib
import suppress) at the top if missing, then wrap the await update_tools(...)
call in a contextlib.suppress(Exception): block so the test preserves the
original intent (ignore exceptions from incomplete mocking) without using a bare
except/pass.

Comment on lines +1890 to +1893
return []

mock_client.connect_to_server = mock_connect
mock_client._connected = False
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Fix unused arguments and boolean‑trap in second mock connect_to_server

Make boolean arg keyword‑only and prefix unused params.

-        async def mock_connect(url, headers=None, sse_read_timeout_seconds=30, verify_ssl=True):
-            connect_called_with["verify_ssl"] = verify_ssl
-            return []
+        async def mock_connect(_url, _headers=None, *, _sse_read_timeout_seconds=30, verify_ssl: bool = True):
+            connect_called_with["verify_ssl"] = verify_ssl
+            return []
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async def mock_connect(url, headers=None, sse_read_timeout_seconds=30, verify_ssl=True):
connect_called_with["verify_ssl"] = verify_ssl
return []
async def mock_connect(_url, _headers=None, *, _sse_read_timeout_seconds=30, verify_ssl: bool = True):
connect_called_with["verify_ssl"] = verify_ssl
return []
🧰 Tools
🪛 GitHub Check: Ruff Style Check (3.13)

[failure] 1888-1888: Ruff (ARG001)
src/backend/tests/unit/base/mcp/test_mcp_util.py:1888:37: ARG001 Unused function argument: headers


[failure] 1888-1888: Ruff (ARG001)
src/backend/tests/unit/base/mcp/test_mcp_util.py:1888:32: ARG001 Unused function argument: url

🤖 Prompt for AI Agents
In src/backend/tests/unit/base/mcp/test_mcp_util.py around lines 1888-1891, the
mock connect function accepts unused positional params and a boolean that can be
accidentally passed positionally; make unused parameters name-prefixed with an
underscore (e.g. _url, _headers) and make boolean args keyword-only by adding a
bare * before them (so verify_ssl must be passed by name), then update the body
to use verify_ssl to record connect_called_with["verify_ssl"] and return the
same stub value; apply the same rename/keyword-only pattern to the other mock
connect_to_server in the same test file to avoid boolean-trap and
unused-argument warnings.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/lfx/src/lfx/base/mcp/util.py (1)

1348-1350: Honor verify_ssl on remote session DELETE

When verify_ssl=False, DELETE may fail to connect to self-signed endpoints. Use the stored flag.

-            async with httpx.AsyncClient(timeout=5.0) as client:
+            async with httpx.AsyncClient(
+                timeout=5.0,
+                verify=bool(self._connection_params.get("verify_ssl", True)),
+            ) as client:
                 await client.delete(url, headers=headers)
🧹 Nitpick comments (4)
src/backend/tests/unit/base/mcp/test_mcp_util.py (2)

1629-1713: Strengthen httpx client factory tests; avoid private attrs and resource leaks

  • Accessing client._transport is relying on httpx internals; brittle.
  • isinstance(client, type(client)) asserts nothing.
  • These tests instantiate AsyncClient without closing it (ResourceWarning risk).

Patch httpx.AsyncClient and assert kwargs instead; no real client needed:

@@
-        client = create_mcp_http_client_with_ssl_option()
-
-        # Verify that SSL verification is enabled by default using _transport
-        # httpx stores verify in the transport config, not as a direct attribute
-        assert client._transport is not None or client.is_closed
-        # Just verify the client was created successfully with default settings
-        assert isinstance(client, type(client))
+        with patch("lfx.base.mcp.util.httpx.AsyncClient") as mock_client:
+            create_mcp_http_client_with_ssl_option()
+            mock_client.assert_called_once()
+            assert mock_client.call_args.kwargs.get("verify") is True
@@
-        client = create_mcp_http_client_with_ssl_option(verify_ssl=False)
-
-        # Verify client was created successfully
-        assert isinstance(client, type(client))
+        with patch("lfx.base.mcp.util.httpx.AsyncClient") as mock_client:
+            create_mcp_http_client_with_ssl_option(verify_ssl=False)
+            mock_client.assert_called_once()
+            assert mock_client.call_args.kwargs.get("verify") is False
@@
-        client = create_mcp_http_client_with_ssl_option(headers=test_headers, verify_ssl=False)
-
-        # Verify headers are set correctly
-        assert client.headers["Authorization"] == "Bearer token123"
-        assert client.headers["X-API-Key"] == "secret"
+        with patch("lfx.base.mcp.util.httpx.AsyncClient") as mock_client:
+            create_mcp_http_client_with_ssl_option(headers=test_headers, verify_ssl=False)
+            called_headers = mock_client.call_args.kwargs.get("headers")
+            assert called_headers == test_headers
@@
-        client = create_mcp_http_client_with_ssl_option(timeout=custom_timeout, verify_ssl=False)
-
-        # Verify timeout is set correctly - httpx.Timeout has read attribute
-        assert client.timeout.read == 120.0
+        with patch("lfx.base.mcp.util.httpx.AsyncClient") as mock_client:
+            create_mcp_http_client_with_ssl_option(timeout=custom_timeout, verify_ssl=False)
+            assert mock_client.call_args.kwargs.get("timeout") == custom_timeout
@@
-        client = create_mcp_http_client_with_ssl_option(auth=auth, verify_ssl=False)
-
-        # Verify auth is set correctly
-        assert client.auth == auth
+        with patch("lfx.base.mcp.util.httpx.AsyncClient") as mock_client:
+            create_mcp_http_client_with_ssl_option(auth=auth, verify_ssl=False)
+            assert mock_client.call_args.kwargs.get("auth") == auth
@@
-        client = create_mcp_http_client_with_ssl_option(
-            headers=test_headers, timeout=custom_timeout, auth=auth, verify_ssl=False
-        )
-
-        # Verify all options are set correctly
-        assert client.headers["Authorization"] == "Bearer token123"
-        assert client.timeout == custom_timeout
-        assert client.auth == auth
+        with patch("lfx.base.mcp.util.httpx.AsyncClient") as mock_client:
+            create_mcp_http_client_with_ssl_option(
+                headers=test_headers, timeout=custom_timeout, auth=auth, verify_ssl=False
+            )
+            kwargs = mock_client.call_args.kwargs
+            assert kwargs.get("headers") == test_headers
+            assert kwargs.get("timeout") == custom_timeout
+            assert kwargs.get("auth") == auth

1833-1911: Good coverage for update_tools verify_ssl behavior

  • Verifies False is passed through when specified.
  • Verifies default to True when omitted.

Consider also asserting headers normalization with _process_headers in a follow-up.

src/lfx/src/lfx/base/mcp/util.py (2)

68-105: httpx AsyncClient factory with verify flag — solid

Clear API, sensible defaults, and explicit verify wiring. Consider allowing explicit connect/read/write timeouts later if needed.


710-745: Guard httpx_client_factory kwarg for MCP SDK compatibility

Passing httpx_client_factory assumes the installed MCP SDK supports it. To avoid runtime TypeError on older versions, gate on the callable’s signature.

@@
-        def custom_httpx_factory(
+        def custom_httpx_factory(
             headers: dict[str, str] | None = None,
             timeout: httpx.Timeout | None = None,
             auth: httpx.Auth | None = None,
         ) -> httpx.AsyncClient:
             return create_mcp_http_client_with_ssl_option(
                 headers=headers, timeout=timeout, auth=auth, verify_ssl=verify_ssl
             )
@@
-                    async with streamablehttp_client(
-                        url=connection_params["url"],
-                        headers=connection_params["headers"],
-                        timeout=connection_params["timeout_seconds"],
-                        httpx_client_factory=custom_httpx_factory,
-                    ) as (read, write, _):
+                    import inspect as _ins
+                    _kwargs = dict(
+                        url=connection_params["url"],
+                        headers=connection_params["headers"],
+                        timeout=connection_params["timeout_seconds"],
+                    )
+                    if "httpx_client_factory" in _ins.signature(streamablehttp_client).parameters:
+                        _kwargs["httpx_client_factory"] = custom_httpx_factory
+                    async with streamablehttp_client(**_kwargs) as (read, write, _):
@@
-                    async with sse_client(
-                        connection_params["url"],
-                        connection_params["headers"],
-                        connection_params["timeout_seconds"],
-                        sse_read_timeout,
-                        httpx_client_factory=custom_httpx_factory,
-                    ) as (read, write):
+                    import inspect as _ins
+                    _args = [
+                        connection_params["url"],
+                        connection_params["headers"],
+                        connection_params["timeout_seconds"],
+                        sse_read_timeout,
+                    ]
+                    _kwargs = {}
+                    if "httpx_client_factory" in _ins.signature(sse_client).parameters:
+                        _kwargs["httpx_client_factory"] = custom_httpx_factory
+                    async with sse_client(*_args, **_kwargs) as (read, write):

Please confirm your MCP SDK version exposes httpx_client_factory on streamablehttp_client and sse_client. If yes, the guard is optional; if not, it prevents a crash. Based on learnings

Also applies to: 756-761, 796-802

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 354a6ce and 394a848.

📒 Files selected for processing (4)
  • src/backend/base/langflow/initial_setup/starter_projects/Nvidia Remix.json (3 hunks)
  • src/backend/tests/unit/base/mcp/test_mcp_util.py (1 hunks)
  • src/lfx/src/lfx/base/mcp/util.py (9 hunks)
  • src/lfx/src/lfx/components/agents/mcp_component.py (3 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
{src/backend/**/*.py,tests/**/*.py,Makefile}

📄 CodeRabbit inference engine (.cursor/rules/backend_development.mdc)

{src/backend/**/*.py,tests/**/*.py,Makefile}: Run make format_backend to format Python code before linting or committing changes
Run make lint to perform linting checks on backend Python code

Files:

  • src/backend/tests/unit/base/mcp/test_mcp_util.py
src/backend/tests/unit/**/*.py

📄 CodeRabbit inference engine (.cursor/rules/backend_development.mdc)

Test component integration within flows using create_flow, build_flow, and get_build_events utilities

Files:

  • src/backend/tests/unit/base/mcp/test_mcp_util.py
src/backend/tests/**/*.py

📄 CodeRabbit inference engine (.cursor/rules/testing.mdc)

src/backend/tests/**/*.py: Unit tests for backend code must be located in the 'src/backend/tests/' directory, with component tests organized by component subdirectory under 'src/backend/tests/unit/components/'.
Test files should use the same filename as the component under test, with an appropriate test prefix or suffix (e.g., 'my_component.py' → 'test_my_component.py').
Use the 'client' fixture (an async httpx.AsyncClient) for API tests in backend Python tests, as defined in 'src/backend/tests/conftest.py'.
When writing component tests, inherit from the appropriate base class in 'src/backend/tests/base.py' (ComponentTestBase, ComponentTestBaseWithClient, or ComponentTestBaseWithoutClient) and provide the required fixtures: 'component_class', 'default_kwargs', and 'file_names_mapping'.
Each test in backend Python test files should have a clear docstring explaining its purpose, and complex setups or mocks should be well-commented.
Test both sync and async code paths in backend Python tests, using '@pytest.mark.asyncio' for async tests.
Mock external dependencies appropriately in backend Python tests to isolate unit tests from external services.
Test error handling and edge cases in backend Python tests, including using 'pytest.raises' and asserting error messages.
Validate input/output behavior and test component initialization and configuration in backend Python tests.
Use the 'no_blockbuster' pytest marker to skip the blockbuster plugin in tests when necessary.
Be aware of ContextVar propagation in async tests; test both direct event loop execution and 'asyncio.to_thread' scenarios to ensure proper context isolation.
Test error handling by mocking internal functions using monkeypatch in backend Python tests.
Test resource cleanup in backend Python tests by using fixtures that ensure proper initialization and cleanup of resources.
Test timeout and performance constraints in backend Python tests using 'asyncio.wait_for' and timing assertions.
Test Langflow's Messag...

Files:

  • src/backend/tests/unit/base/mcp/test_mcp_util.py
**/@(test_*.py|*.test.@(ts|tsx))

📄 CodeRabbit inference engine (coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt)

**/@(test_*.py|*.test.@(ts|tsx)): Check if tests have too many mock objects that obscure what's actually being tested
Warn when mocks are used instead of testing real behavior and interactions
Suggest using real objects or test doubles when mocks become excessive
Ensure mocks are used appropriately for external dependencies, not core logic
Recommend integration tests when unit tests become overly mocked
Test files should have descriptive test function names explaining what is tested
Tests should be organized logically with proper setup and teardown
Include edge cases and error conditions for comprehensive coverage
Verify tests cover both positive and negative scenarios where appropriate
Tests should cover the main functionality being implemented
Ensure tests are not just smoke tests but actually validate behavior
For API endpoints, verify both success and error response testing

Files:

  • src/backend/tests/unit/base/mcp/test_mcp_util.py
**/test_*.py

📄 CodeRabbit inference engine (coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt)

**/test_*.py: Check that backend test files follow naming convention: test_.py
Backend tests should be named test_
.py and follow proper pytest structure
For async Python code, ensure proper async testing patterns (pytest) are used
Backend tests should follow pytest conventions; frontend tests should use Playwright

Files:

  • src/backend/tests/unit/base/mcp/test_mcp_util.py
🧬 Code graph analysis (2)
src/lfx/src/lfx/components/agents/mcp_component.py (1)
src/lfx/src/lfx/inputs/inputs.py (1)
  • BoolInput (414-426)
src/backend/tests/unit/base/mcp/test_mcp_util.py (1)
src/lfx/src/lfx/base/mcp/util.py (6)
  • create_mcp_http_client_with_ssl_option (68-104)
  • MCPStreamableHttpClient (1213-1483)
  • connect_to_server (1048-1052)
  • connect_to_server (1296-1309)
  • MCPSessionManager (438-997)
  • update_tools (1491-1636)
🔇 Additional comments (3)
src/backend/tests/unit/base/mcp/test_mcp_util.py (1)

1741-1771: Nice propagation check for verify_ssl in connect_to_server

Good validation of connection parameters and storage of verify_ssl in _connection_params.

src/lfx/src/lfx/components/agents/mcp_component.py (1)

64-65: Expose and propagate verify_ssl — LGTM

  • default_keys includes verify_ssl so it won’t be stripped from build_config.
  • BoolInput is clear, advanced, defaults True with a good warning.
  • update_tool_list sets server_config["verify_ssl"] when missing.

No issues spotted.

Also applies to: 90-99, 224-228

src/lfx/src/lfx/base/mcp/util.py (1)

1248-1278: verify_ssl propagation through connection params and update_tools — LGTM

  • _connect_to_server stores verify_ssl.
  • connect_to_server plumbs it through.
  • update_tools passes verify_ssl from server_config.

Looks correct and consistent with tests.

Also applies to: 1296-1309, 1538-1540

Copy link
Copy Markdown
Collaborator

@lucaseduoli lucaseduoli left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Oct 21, 2025
@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Oct 21, 2025
@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Oct 21, 2025
@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Oct 21, 2025
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Oct 21, 2025

Frontend Unit Test Coverage Report

Coverage Summary

Lines Statements Branches Functions
Coverage: 11%
10.84% (2890/26653) 4.54% (926/20374) 6.36% (372/5843)

Unit Test Results

Tests Skipped Failures Errors Time
1207 0 💤 0 ❌ 0 🔥 13.917s ⏱️

@edwinjosechittilappilly edwinjosechittilappilly removed the lgtm This PR has been approved by a maintainer label Oct 21, 2025
@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Oct 22, 2025
@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Oct 22, 2025
autofix-ci Bot and others added 2 commits October 22, 2025 16:04
Updated component_index.json to include new Notion integration components: AddContentToPage, NotionDatabaseProperties, NotionListPages, NotionPageContent, NotionPageCreator, NotionPageUpdate, and NotionSearch. These components provide functionality for interacting with Notion databases and pages, including creating, updating, listing, searching, and retrieving content.
@github-actions github-actions Bot removed the enhancement New feature or request label Oct 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants