Skip to content

LCORE-1371: MCP OAuth Integration Tests#1218

Merged
tisnik merged 5 commits intolightspeed-core:mainfrom
jrobertboos:lcore-1371
Mar 3, 2026
Merged

LCORE-1371: MCP OAuth Integration Tests#1218
tisnik merged 5 commits intolightspeed-core:mainfrom
jrobertboos:lcore-1371

Conversation

@jrobertboos
Copy link
Contributor

@jrobertboos jrobertboos commented Feb 24, 2026

Description

Created integration tests for the MCP OAuth flow on the following endpoints:

  • /tools
  • /query
  • /streaming_query

Type of change

  • Refactor
  • New feature
  • Bug fix
  • CVE fix
  • Optimization
  • Documentation Update
  • Configuration Update
  • Bump-up service version
  • Bump-up dependent library
  • Bump-up library or tool used for development (does not change the final image)
  • CI configuration change
  • Konflux configuration change
  • Unit tests improvement
  • Integration tests improvement
  • End to end tests improvement
  • Benchmarks improvement

Tools used to create PR

Identify any AI code assistants used in this PR (for transparency and review context)

  • Assisted-by: Cursor
  • Generated by: Cursor

Related Tickets & Documents

  • Related Issue #
  • Closes LCORE-1371

Checklist before requesting a review

  • I have performed a self-review of my code.
  • PR has passed all pre-merge test jobs.
  • If it is a core feature, I have added thorough tests.

Testing

make test-integration

Summary by CodeRabbit

  • Tests
    • Added integration tests for query, streaming-query, and tools endpoints to verify MCP OAuth 401s are forwarded to clients.
    • Covers 401 responses that include a WWW-Authenticate header and 401 responses without the header (e.g., probe timeout).
    • Added fixtures/mocks to simulate external client behavior and OAuth probe outcomes for these scenarios.

…points to verify 401 responses with WWW-Authenticate when MCP OAuth is required. Add mock fixtures for Llama Stack client interactions in each test file.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 24, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2fd2d11 and 23571da.

📒 Files selected for processing (2)
  • tests/integration/endpoints/test_streaming_query_integration.py
  • tests/integration/endpoints/test_tools_integration.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/integration/endpoints/test_tools_integration.py
  • tests/integration/endpoints/test_streaming_query_integration.py

Walkthrough

Adds integration tests and fixtures verifying that the /query (v2), /streaming_query, and /tools endpoints propagate MCP OAuth HTTP 401 responses, both with and without a WWW-Authenticate header.

Changes

Cohort / File(s) Summary
Query endpoint tests
tests/integration/endpoints/test_query_integration.py
Adds two tests that patch get_mcp_tools to raise HTTP 401 (with and without WWW-Authenticate) and assert the v2 /query handler forwards the 401 and header behavior.
Streaming query endpoint tests
tests/integration/endpoints/test_streaming_query_integration.py
Adds two async tests that patch get_mcp_tools to raise HTTP 401 (with and without WWW-Authenticate) and assert /streaming_query forwards the 401 and header behavior; reuses existing streaming fixtures.
Tools endpoint tests
tests/integration/endpoints/test_tools_integration.py
New module: fixture mock_llama_stack_tools and two tests simulating tools.list AuthenticationError and MCP OAuth probe behavior (explicit 401 with WWW-Authenticate and timeout producing 401 without the header); asserts /tools forwards the HTTP 401 details.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

Suggested reviewers

  • radofuchs
  • tisnik
🚥 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 clearly and concisely summarizes the main change: adding MCP OAuth integration tests across multiple endpoints (/tools, /query, /streaming_query).
Docstring Coverage ✅ Passed Docstring coverage is 100.00% 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 unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

Copy link
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.

♻️ Duplicate comments (1)
tests/integration/endpoints/test_streaming_query_integration.py (1)

76-80: ⚠️ Potential issue | 🟠 Major

Same potentially incorrect patch target as in test_query_integration.py.

"utils.responses.get_mcp_tools" patches the definition site. If app.endpoints.streaming_query imports the function directly (from utils.responses import get_mcp_tools), the mock won't intercept calls from that module. Verify and, if needed, patch "app.endpoints.streaming_query.get_mcp_tools" instead.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/integration/endpoints/test_streaming_query_integration.py` around lines
76 - 80, The mock currently patches "utils.responses.get_mcp_tools" which may
not intercept calls if streaming_query imports get_mcp_tools directly; update
the test to patch the symbol used by the code under test by replacing the target
with "app.endpoints.streaming_query.get_mcp_tools" (or confirm the import style
in app.endpoints.streaming_query and patch that module's get_mcp_tools) so the
AsyncMock side_effect oauth_401 is applied where streaming_query calls
get_mcp_tools.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@tests/integration/endpoints/test_streaming_query_integration.py`:
- Around line 76-80: The mock currently patches "utils.responses.get_mcp_tools"
which may not intercept calls if streaming_query imports get_mcp_tools directly;
update the test to patch the symbol used by the code under test by replacing the
target with "app.endpoints.streaming_query.get_mcp_tools" (or confirm the import
style in app.endpoints.streaming_query and patch that module's get_mcp_tools) so
the AsyncMock side_effect oauth_401 is applied where streaming_query calls
get_mcp_tools.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 051c06c and a70355c.

📒 Files selected for processing (3)
  • tests/integration/endpoints/test_query_integration.py
  • tests/integration/endpoints/test_streaming_query_integration.py
  • tests/integration/endpoints/test_tools_integration.py

…es out in query, streaming_query, and tools endpoints. Each test verifies that a 401 status is returned without a WWW-Authenticate header upon timeout.
Copy link
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 (1)
tests/integration/endpoints/test_query_integration.py (1)

293-344: Test approach inconsistency vs. test_tools_integration.py for the timeout scenario.

test_query_v2_endpoint_returns_401_when_oauth_probe_times_out mocks get_mcp_tools directly to raise a 401, skipping the real probe_mcp_oauth_and_raise_401 / aiohttp path entirely. The analogous test in test_tools_integration.py (test_tools_endpoint_returns_401_when_oauth_probe_times_out) exercises the real probe by mocking aiohttp.ClientSession to raise TimeoutError. This gap means the query-side timeout path through the probe function itself is untested.

Consider adopting the same deeper integration strategy used in test_tools_integration.py if the intent is to validate the full timeout propagation path.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/integration/endpoints/test_query_integration.py` around lines 293 -
344, The test test_query_v2_endpoint_returns_401_when_oauth_probe_times_out
currently mocks get_mcp_tools directly; instead simulate the real timeout path
by letting get_mcp_tools call probe_mcp_oauth_and_raise_401 and cause a
TimeoutError in the HTTP layer (like the pattern in test_tools_integration.py).
Replace the direct mock of get_mcp_tools with a mock that patches
aiohttp.ClientSession (or the underlying session.request) to raise
asyncio.TimeoutError during the probe so probe_mcp_oauth_and_raise_401 raises
the same 401-without-WWW-Authenticate, then assert query_endpoint_handler
propagates that HTTPException; reference functions:
test_query_v2_endpoint_returns_401_when_oauth_probe_times_out, get_mcp_tools,
probe_mcp_oauth_and_raise_401, and aiohttp.ClientSession.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/integration/endpoints/test_tools_integration.py`:
- Line 123: The long line creating the patch call exceeds Black's line length;
break the call into multiple lines using implicit continuation with parentheses
so Black can reformat it. Locate the mocker.patch invocation that targets
"utils.mcp_oauth_probe.aiohttp.ClientSession" and rewrite it across lines (e.g.,
put the target string on its own line and the return_value=mock_session_cm on
the next line inside parentheses) so the call remains the same but fits within
the formatter's column limit.

---

Nitpick comments:
In `@tests/integration/endpoints/test_query_integration.py`:
- Around line 293-344: The test
test_query_v2_endpoint_returns_401_when_oauth_probe_times_out currently mocks
get_mcp_tools directly; instead simulate the real timeout path by letting
get_mcp_tools call probe_mcp_oauth_and_raise_401 and cause a TimeoutError in the
HTTP layer (like the pattern in test_tools_integration.py). Replace the direct
mock of get_mcp_tools with a mock that patches aiohttp.ClientSession (or the
underlying session.request) to raise asyncio.TimeoutError during the probe so
probe_mcp_oauth_and_raise_401 raises the same 401-without-WWW-Authenticate, then
assert query_endpoint_handler propagates that HTTPException; reference
functions: test_query_v2_endpoint_returns_401_when_oauth_probe_times_out,
get_mcp_tools, probe_mcp_oauth_and_raise_401, and aiohttp.ClientSession.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a70355c and 78ea325.

📒 Files selected for processing (3)
  • tests/integration/endpoints/test_query_integration.py
  • tests/integration/endpoints/test_streaming_query_integration.py
  • tests/integration/endpoints/test_tools_integration.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/integration/endpoints/test_streaming_query_integration.py

Copy link
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.

🧹 Nitpick comments (1)
tests/integration/endpoints/test_tools_integration.py (1)

48-48: Prefer @pytest.mark.usefixtures over discarding the fixture value.

_ = test_config is used solely to activate the fixture. The more idiomatic pytest pattern is to annotate the test with @pytest.mark.usefixtures("test_config") and remove the parameter from the signature, which makes the intent clearer.

Same applies to line 102.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/integration/endpoints/test_tools_integration.py` at line 48, Replace
the pattern of accepting and discarding the fixture value by using pytest's
usefixtures marker: remove the test_config parameter from the test function
signatures where you only do `_ = test_config` and instead annotate those tests
with `@pytest.mark.usefixtures`("test_config") (apply to both occurrences around
lines with `_ = test_config`, e.g., the tests in
tests/integration/endpoints/test_tools_integration.py that currently accept
test_config as a parameter).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@tests/integration/endpoints/test_tools_integration.py`:
- Line 48: Replace the pattern of accepting and discarding the fixture value by
using pytest's usefixtures marker: remove the test_config parameter from the
test function signatures where you only do `_ = test_config` and instead
annotate those tests with `@pytest.mark.usefixtures`("test_config") (apply to both
occurrences around lines with `_ = test_config`, e.g., the tests in
tests/integration/endpoints/test_tools_integration.py that currently accept
test_config as a parameter).

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 78ea325 and 6e180c3.

📒 Files selected for processing (1)
  • tests/integration/endpoints/test_tools_integration.py

@jrobertboos
Copy link
Contributor Author

Hey @radofuchs do you think that you could review this?

@jrobertboos jrobertboos requested a review from tisnik March 2, 2026 16:45
Copy link
Contributor

@radofuchs radofuchs left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Contributor

@tisnik tisnik left a comment

Choose a reason for hiding this comment

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

LGTM

@tisnik tisnik merged commit 528738d into lightspeed-core:main Mar 3, 2026
22 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.

3 participants