Skip to content

fix: Update Lasso plugin to v3 API and support non-chat argument formats#13

Merged
oroxenberg merged 4 commits intomainfrom
fix/lasso-v3-api-and-argument-extraction
Jan 21, 2026
Merged

fix: Update Lasso plugin to v3 API and support non-chat argument formats#13
oroxenberg merged 4 commits intomainfrom
fix/lasso-v3-api-and-argument-extraction

Conversation

@eliransu
Copy link
Contributor

@eliransu eliransu commented Jan 21, 2026

  • Update Lasso API endpoint from v2 to v3
  • Add messageType field to API payload (required by v3)
  • Add _extract_string_values() to recursively extract all string values from nested dicts/lists
  • Update _extract_messages_from_request() to extract arguments from any MCP tool format, not just chat-style messages array
  • Remove deprecated license classifier from pyproject.toml
  • Remove unsupported 'version' argument from FastMCP init

This enables Lasso guardrails to work with MCP servers like falcon-mcp that use filter/query style arguments instead of chat messages format.


Note

Lasso guardrail updates

  • Switch default API endpoint to v3 and include messageType in request payloads
  • Add _extract_string_values and enhance _extract_messages_from_request to support non-chat argument formats (e.g., filter/query), with improved debug logging
  • Simplify response parsing by relying on content and removing deprecated outputs handling

Gateway and project maintenance

  • Remove unsupported version argument from FastMCP initialization in gateway.py
  • Clean up pyproject.toml classifiers

Tests

  • Update/add tests to reflect v3 defaults and new message extraction behavior

Written by Cursor Bugbot for commit 97b3d0d. This will update automatically on new commits. Configure here.

Summary by CodeRabbit

  • Updates
    • Guardrails plugin default API bumped to v3; payloads can include a message type field.
  • Bug Fixes
    • More robust message parsing with recursive string extraction and improved response parsing and logging.
  • Chores
    • Removed explicit gateway version propagation from startup configuration; project metadata classifier adjusted.
  • Tests
    • Tests updated/added to reflect API v3 and recursive string-extraction behavior.

✏️ Tip: You can customize this high-level summary in your review settings.

- Update Lasso API endpoint from v2 to v3
- Add messageType field to API payload (required by v3)
- Add _extract_string_values() to recursively extract all string values
  from nested dicts/lists
- Update _extract_messages_from_request() to extract arguments from
  any MCP tool format, not just chat-style messages array
- Remove deprecated license classifier from pyproject.toml
- Remove unsupported 'version' argument from FastMCP init

This enables Lasso guardrails to work with MCP servers like falcon-mcp
that use filter/query style arguments instead of chat messages format.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@coderabbitai
Copy link

coderabbitai bot commented Jan 21, 2026

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

Walkthrough

Removed explicit version from FastMCP instantiation, upgraded Lasso guardrail to use the v3 classify endpoint with enhanced message extraction (including recursive string extraction and optional message_type in payload), and deleted the MIT license classifier from project metadata.

Changes

Cohort / File(s) Summary
Gateway Configuration
mcp_gateway/gateway.py
Removed version="1.0.0" from FastMCP("MCP Gateway", ...) instantiation.
Lasso Guardrail Plugin
mcp_gateway/plugins/guardrails/lasso.py
API base bumped from v2v3 classify endpoint; _prepare_payload adds messageType and accepts message_type: str = "PROMPT"; message extraction now prefers messages and falls back to a new recursive _extract_string_values that aggregates non-empty strings; response parsing simplified and logging updated.
Project Metadata
pyproject.toml
Removed "License :: OSI Approved :: MIT License" from [project].classifiers.
Tests
tests/test_lasso_guardrail.py
Updated expected API base to v3; added tests for _extract_string_values and for fallback message extraction behavior.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Guardrail as LassoGuardrailPlugin
    participant LassoAPI as External Lasso API
    Client->>Guardrail: call guardrail with args / messages
    alt messages present
        Guardrail->>Guardrail: use provided messages list
    else no messages
        Guardrail->>Guardrail: _extract_string_values(args) → list of strings
        Guardrail->>Guardrail: combine into single user message
    end
    Guardrail->>LassoAPI: POST /v3/classify (payload includes messageType)
    LassoAPI-->>Guardrail: classification response
    Guardrail-->>Client: return classification result
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I nibbled code beneath the moonlight bright,
I swapped a version and tuned Lasso's sight,
I gathered stray strings from nests so deep,
Packaged each message before falling asleep—
Hoppity hop, a tiny change, a joyful leap!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately captures the main changes: updating Lasso plugin to v3 API and adding support for non-chat argument formats, which are the core objectives of the PR.
Docstring Coverage ✅ Passed Docstring coverage is 92.31% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

📜 Recent review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7a1c0a9 and 97b3d0d.

📒 Files selected for processing (2)
  • mcp_gateway/plugins/guardrails/lasso.py
  • tests/test_lasso_guardrail.py
🧰 Additional context used
🧬 Code graph analysis (1)
tests/test_lasso_guardrail.py (1)
mcp_gateway/plugins/guardrails/lasso.py (3)
  • LassoGuardrailPlugin (22-337)
  • _extract_string_values (157-167)
  • _extract_messages_from_request (169-210)
🪛 Ruff (0.14.13)
mcp_gateway/plugins/guardrails/lasso.py

157-157: Dynamically typed expressions (typing.Any) are disallowed in obj

(ANN401)


174-174: Logging statement uses f-string

(G004)


204-204: Logging statement uses f-string

(G004)

⏰ 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). (1)
  • GitHub Check: Cursor Bugbot
🔇 Additional comments (6)
mcp_gateway/plugins/guardrails/lasso.py (4)

34-34: LGTM! API base and docstring updated to v3.

The endpoint and documentation are now consistent with the v3 API.

Also applies to: 45-45


157-167: LGTM! Clean recursive extraction logic.

The helper correctly handles nested dicts/lists, filters empty strings, and safely ignores non-string types. The Any type annotation is appropriate for this utility that processes arbitrary nested structures.


191-206: LGTM! Fallback extraction now preserves argument context.

The updated logic includes argument keys in the extracted content (e.g., "filter: value; query: value2"), which improves traceability for guardrail checks. Logging level is correctly set to DEBUG.


99-103: Unable to verify the correct messageType value for response validation without official Lasso API documentation.

While the code at line 311 does call _prepare_payload(messages) without specifying a message type in process_response, defaulting to "PROMPT" for assistant content, I cannot confirm whether this is incorrect or whether "RESPONSE" is the proper value. The codebase contains no tests validating different messageType values, no documentation explaining their semantics, and the Lasso API v3 specification is not publicly available in searchable sources.

The concern about consistent messageType values between process_request and process_response is valid and worth confirming with Lasso's API documentation, but the specific fix proposed cannot be verified without that reference.

tests/test_lasso_guardrail.py (2)

66-66: LGTM! Assertion updated for v3 endpoint.


148-169: LGTM! Test validates the core PR objective.

The test correctly verifies that non-chat-style arguments (like filter/query used by falcon-mcp) are extracted with argument keys preserved in the content, while non-string values are ignored.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.


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

Copy link

@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

🤖 Fix all issues with AI agents
In `@mcp_gateway/plugins/guardrails/lasso.py`:
- Line 38: Update the module/class docstring that still references the v2 Lasso
endpoint so it matches the actual configured API base (self.api_base =
"https://server.lasso.security/gateway/v3/classify"); locate the docstring in
lasso.py that mentions the v2 URL and replace it with the v3 URL and any
corresponding wording (e.g., "gateway/v3/classify") to keep the docstring
consistent with the self.api_base value.
📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c8b73bb and 1ca6de9.

📒 Files selected for processing (3)
  • mcp_gateway/gateway.py
  • mcp_gateway/plugins/guardrails/lasso.py
  • pyproject.toml
💤 Files with no reviewable changes (1)
  • pyproject.toml
🧰 Additional context used
🪛 Ruff (0.14.13)
mcp_gateway/plugins/guardrails/lasso.py

159-159: Dynamically typed expressions (typing.Any) are disallowed in obj

(ANN401)


176-176: Logging statement uses f-string

(G004)


202-202: Logging statement uses f-string

(G004)

⏰ 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). (1)
  • GitHub Check: Cursor Bugbot
🔇 Additional comments (4)
mcp_gateway/gateway.py (1)

452-452: LGTM!

Removing the unsupported version argument from FastMCP initialization is correct. The change aligns with the PR objective.

mcp_gateway/plugins/guardrails/lasso.py (3)

159-169: LGTM!

The recursive helper correctly extracts all non-empty string values from arbitrary nested structures. The Any type annotation is appropriate here since MCP tool arguments can have varying structures. The in-place mutation pattern is efficient for this use case.


193-206: LGTM!

The fallback logic to extract all string values from non-chat arguments enables support for MCP tools like falcon-mcp that use filter/query-style arguments. Combining strings into a single user message is a reasonable approach for content scanning purposes.


103-105: Verify messageType parameter handling for response processing against Lasso v3 API specification.

The _prepare_payload method defaults to message_type="PROMPT", which is semantically appropriate for request processing. However, at line 320 in process_response, assistant-generated content is prepared with the same "PROMPT" default. Verify with Lasso v3 API documentation whether responses should use a different messageType (e.g., "RESPONSE", "COMPLETION", or another value) to properly categorize content based on origin.

Also applies to: 320

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

Copy link

@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)
tests/test_lasso_guardrail.py (1)

98-115: Missing test coverage for new non-chat argument extraction.

The PR adds _extract_string_values() and updates _extract_messages_from_request() to handle MCP-style argument formats (filter/query-style arguments), but this test only covers the standard messages list format. Consider adding test cases for:

  1. Fallback extraction when messages key is absent
  2. Nested dict/list structures with string values
  3. Mixed argument formats used by MCP servers like falcon-mcp
📝 Suggested additional test cases
def test_extract_messages_from_request_fallback_format() -> None:
    """Test extracting messages from non-chat MCP argument formats."""
    plugin = LassoGuardrailPlugin()

    # Test filter/query-style arguments without "messages" key
    arguments: Dict[str, Any] = {
        "query": "SELECT * FROM users",
        "filters": {
            "name": "test_user",
            "nested": {"value": "nested_string"}
        }
    }

    messages = plugin._extract_messages_from_request(arguments)

    # Verify string values are extracted from nested structures
    assert len(messages) > 0
    # Verify extracted content contains the string values
    contents = [m["content"] for m in messages]
    assert any("SELECT * FROM users" in c for c in contents)
📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1ca6de9 and 5953eec.

📒 Files selected for processing (1)
  • tests/test_lasso_guardrail.py
⏰ 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). (1)
  • GitHub Check: Cursor Bugbot
🔇 Additional comments (2)
tests/test_lasso_guardrail.py (2)

66-66: LGTM!

The test assertion correctly reflects the API endpoint upgrade from v2 to v3, aligning with the changes in mcp_gateway/plugins/guardrails/lasso.py.


187-189: Verify type compatibility with updated _prepare_payload signature.

According to the summary, _prepare_payload signature changed to accept messages: List[str], but this test passes a List[Dict]. Verify the test is compatible with the updated implementation.

#!/bin/bash
# Description: Check the actual _prepare_payload signature in the implementation
# Expected: Confirm parameter type to verify test compatibility

ast-grep --pattern $'def _prepare_payload(self, $_) {
  $$$
}'

# Fallback: search with ripgrep for more context
rg -n -A 10 'def _prepare_payload' --type py

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

- Remove dead code for non-existent 'outputs' attribute
- Fix docstring to reference v3 API instead of v2
- Change verbose INFO logging to DEBUG level
- Remove unnecessary 'pass' statements from exception classes
- Add comprehensive tests for _extract_string_values()
Copy link

@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: 2

Caution

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

⚠️ Outside diff range comments (1)
tests/test_lasso_guardrail.py (1)

128-145: Missing test coverage for non-chat argument extraction fallback.

The existing test_extract_messages_from_request only tests the chat-style "messages" format. Consider adding a test case for the new fallback path that handles non-chat arguments (e.g., filter/query-style args used by MCP servers like falcon-mcp).

📝 Suggested additional test
def test_extract_messages_from_request_fallback() -> None:
    """Test extracting messages from non-chat request arguments."""
    plugin = LassoGuardrailPlugin()

    # Non-chat style arguments (e.g., filter/query args)
    arguments: Dict[str, Any] = {
        "filter": "status=active",
        "query": "SELECT * FROM users",
        "nested": {"value": "test"}
    }

    messages = plugin._extract_messages_from_request(arguments)

    assert len(messages) == 1
    assert messages[0]["role"] == "user"
    # All string values should be combined
    assert "status=active" in messages[0]["content"]
    assert "SELECT * FROM users" in messages[0]["content"]
    assert "test" in messages[0]["content"]
🤖 Fix all issues with AI agents
In `@mcp_gateway/plugins/guardrails/lasso.py`:
- Around line 191-203: The fallback branch that builds a single user message by
joining extracted strings loses per-argument context and uses the wrong log
level; update the behavior in the block handling when not messages and arguments
by (1) changing logger.info(...) to logger.debug(...) for verbosity consistency,
and (2) preserve argument context by instead creating messages that include
argument keys (e.g., produce one message per argument or include a mapping of
argument name→value) using the existing _extract_string_values helper to obtain
values and then attaching them to messages (refer to variables messages,
arguments, combined_content and method _extract_string_values to locate the code
to modify).

In `@tests/test_lasso_guardrail.py`:
- Around line 98-125: Add a test asserting that None values are ignored by the
helper: in tests/test_lasso_guardrail.py extend test_extract_string_values to
call plugin._extract_string_values with a structure containing None (e.g., {"a":
None, "b": "text"}) and assert the resulting values list contains only the
string entries; reference the helper by name _extract_string_values and ensure
the new assertion follows the existing patterns for values initialization and
equality checks.
♻️ Duplicate comments (1)
mcp_gateway/plugins/guardrails/lasso.py (1)

99-103: messageType defaults to "PROMPT" for response validation.

The process_response method at line 308 calls _prepare_payload(messages) without specifying message_type, causing responses to be validated with "PROMPT" type. If the v3 API distinguishes between prompt and response validation, this could apply incorrect rules to assistant outputs.

Consider passing an appropriate message type for response validation:

         # Prepare and make API call
         headers = self._prepare_headers()
-        payload = self._prepare_payload(messages)
+        payload = self._prepare_payload(messages, message_type="RESPONSE")
         response = await self._call_lasso_api(headers, payload)
Lasso Security API v3 messageType field values for classify endpoint

Also applies to: 306-309

📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5953eec and 7a1c0a9.

📒 Files selected for processing (2)
  • mcp_gateway/plugins/guardrails/lasso.py
  • tests/test_lasso_guardrail.py
🧰 Additional context used
🧬 Code graph analysis (1)
tests/test_lasso_guardrail.py (1)
mcp_gateway/plugins/guardrails/lasso.py (2)
  • LassoGuardrailPlugin (22-334)
  • _extract_string_values (157-167)
🪛 Ruff (0.14.13)
mcp_gateway/plugins/guardrails/lasso.py

157-157: Dynamically typed expressions (typing.Any) are disallowed in obj

(ANN401)


174-174: Logging statement uses f-string

(G004)


201-201: Logging statement uses f-string

(G004)

⏰ 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). (1)
  • GitHub Check: Cursor Bugbot
🔇 Additional comments (6)
mcp_gateway/plugins/guardrails/lasso.py (5)

34-34: Docstring now correctly references v3 API.

The API base URL and documentation have been consistently updated to reference the v3 endpoint.

Also applies to: 45-45


157-167: Recursive string extraction implementation is correct.

The helper correctly handles nested structures. The Any type annotation (flagged by Ruff ANN401) is appropriate here since the function is designed to process arbitrary nested data structures.


209-229: Response text extraction is well-structured.

The simplified implementation correctly handles CallToolResult with TextContent and uses appropriate logging levels.


231-278: Request processing logic is sound.

The fail-open behavior on unexpected errors and the use of "PROMPT" message type for request validation are appropriate.


280-334: Response processing implementation is correct.

The fail-open behavior and error response construction are appropriate. The messageType concern was noted above.

tests/test_lasso_guardrail.py (1)

61-66: LGTM!

Test correctly updated to verify the v3 API endpoint.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

- Include argument keys in extracted content (e.g., 'filter: value')
- Change log level from INFO to DEBUG for consistency
- Add test for fallback extraction behavior
@oroxenberg oroxenberg merged commit 965cb9a into main Jan 21, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants