Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
99a2d04
Add OBO credential flow integration tests
dhruv0811 Mar 2, 2026
82c0416
Fix: use Config(credentials_strategy=...) for ModelServingUserCredent…
dhruv0811 Mar 2, 2026
8cab315
Fix: use credentials_strategy (with 's') — the correct WorkspaceClien…
dhruv0811 Mar 2, 2026
1ad436d
Fix whoami assertions: compare deployer vs end-user SQL results directly
dhruv0811 Mar 2, 2026
0092c63
Format test file with ruff
dhruv0811 Mar 2, 2026
3ac4925
Fix type checker errors: add None guards for SDK optional types
dhruv0811 Mar 2, 2026
760914d
Replace simulated OBO tests with end-to-end agent invocation tests
dhruv0811 Mar 2, 2026
462b5f9
Add databricks-openai to test dependencies for OBO e2e tests
dhruv0811 Mar 2, 2026
dece67c
Add app fixture, serving deploy script, and warm-start for OBO e2e tests
dhruv0811 Mar 3, 2026
93bbaa4
Fix app fixture: add hatch wheel packages config
dhruv0811 Mar 3, 2026
9f7be0c
Add serving agent and deploy script matching working notebook pattern
dhruv0811 Mar 4, 2026
feaa742
Fix lint, format, and core_test failures
dhruv0811 Mar 4, 2026
92817a2
Fix SP-B identity check: use OBO_TEST_CLIENT_ID directly
dhruv0811 Mar 4, 2026
a02ca89
Move whoami_serving_agent.py into model_serving_fixture/
dhruv0811 Mar 4, 2026
f3865dd
Inject warehouse ID at deploy time instead of reading env at import
dhruv0811 Mar 4, 2026
98b4639
Fix app whoami tool: return user_name (UUID for SPs) for parity with …
dhruv0811 Mar 4, 2026
dee9a72
Fix serving deploy: drop endpoint_name, add input_example
dhruv0811 Mar 4, 2026
7ea29d8
Fix ruff: remove unused imports (shutil, os)
dhruv0811 Mar 5, 2026
0be9a50
Fix langchain integration test failures
dhruv0811 Mar 5, 2026
103a20d
Fix langchain integration test failures
dhruv0811 Mar 5, 2026
e57c8a3
Skip remaining 4 failing tests (streaming usage + mock unit test)
dhruv0811 Mar 5, 2026
d2a5966
Add DBSQL and raw streamable_http_client MCP integration tests
dhruv0811 Mar 6, 2026
da1f82d
Add Genie raw streamable_http_client integration test
dhruv0811 Mar 6, 2026
5053533
Refactor raw streamable tests to use pytest.mark.asyncio
dhruv0811 Mar 6, 2026
437e7ff
Fix langchain integration tests (comprehensive)
dhruv0811 Mar 9, 2026
6f1cc31
Remove RUN_DOGFOOD_TESTS gates — run all tests for evaluation
dhruv0811 Mar 9, 2026
8011e00
Remove RUN_ST_ENDPOINT_TESTS gates — run all tests for evaluation
dhruv0811 Mar 9, 2026
624be6c
Fix langchain integration tests (clean diff from main)
dhruv0811 Mar 9, 2026
5a1f939
Fix timeout_and_retries unit test: patch get_openai_client directly
dhruv0811 Mar 9, 2026
9e1c9ee
Revert stream_options, fix remaining issues
dhruv0811 Mar 9, 2026
30fc2e6
Fix streaming usage tests: find usage chunk instead of assuming last
dhruv0811 Mar 9, 2026
9a94116
Remove OBO file changes that belong to PR #352
dhruv0811 Mar 13, 2026
fb8ad59
Fix ruff formatting
dhruv0811 Mar 13, 2026
650a974
Fix ty errors: add assert for type narrowing in lakebase tests
dhruv0811 Mar 13, 2026
7a2ec0d
Fix ty error: narrow union type before accessing .text
dhruv0811 Mar 18, 2026
7a5b3cc
Address PR review: remove DBSQL skip, extract raw_mcp_session helper
dhruv0811 Mar 18, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions databricks_mcp/tests/integration_tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,32 @@ def cached_vs_call_result(vs_mcp_client, cached_vs_tools_list):
return vs_mcp_client.call_tool(tool.name, {param_name: "test"})


# =============================================================================
# DBSQL Fixtures
# =============================================================================


@pytest.fixture(scope="session")
def dbsql_mcp_url(workspace_client):
"""Construct MCP URL for the DBSQL server."""
base_url = workspace_client.config.host
return f"{base_url}/api/2.0/mcp/sql"


@pytest.fixture(scope="session")
def dbsql_mcp_client(dbsql_mcp_url, workspace_client):
"""DatabricksMCPClient pointed at the DBSQL server."""
return DatabricksMCPClient(dbsql_mcp_url, workspace_client)


@pytest.fixture(scope="session")
def cached_dbsql_tools_list(dbsql_mcp_client):
"""Cache the DBSQL list_tools() result."""
tools = dbsql_mcp_client.list_tools()
assert tools, "DBSQL list_tools() returned no tools"
return tools


# =============================================================================
# Genie Fixtures
# =============================================================================
Expand Down
114 changes: 114 additions & 0 deletions databricks_mcp/tests/integration_tests/test_mcp_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,38 @@
from __future__ import annotations

import os
from contextlib import asynccontextmanager

import pytest
from conftest import _skip_if_not_found
from mcp.shared.exceptions import McpError
from mcp.types import CallToolResult


@asynccontextmanager
async def raw_mcp_session(url, workspace_client):
"""Create a raw MCP ClientSession using streamable_http_client with Databricks OAuth."""
import httpx
from mcp import ClientSession
from mcp.client.streamable_http import streamable_http_client

from databricks_mcp import DatabricksOAuthClientProvider

async with httpx.AsyncClient(
auth=DatabricksOAuthClientProvider(workspace_client),
follow_redirects=True,
timeout=httpx.Timeout(120.0, read=120.0),
) as http_client:
async with streamable_http_client(url, http_client=http_client) as (
read_stream,
write_stream,
_,
):
async with ClientSession(read_stream, write_stream) as session:
await session.initialize()
yield session


from databricks_mcp import DatabricksMCPClient

pytestmark = pytest.mark.skipif(
Expand Down Expand Up @@ -126,6 +152,94 @@ def test_call_tool_returns_result_with_content(self, cached_genie_call_result):
assert len(cached_genie_call_result.content) > 0


# =============================================================================
# DBSQL
# =============================================================================


@pytest.mark.integration
class TestMCPClientDBSQL:
"""Verify list_tools() and call_tool() against a live DBSQL MCP server."""

def test_list_tools_returns_expected_tools(self, cached_dbsql_tools_list):
tool_names = [t.name for t in cached_dbsql_tools_list]
for expected in ["execute_sql", "execute_sql_read_only", "poll_sql_result"]:
assert expected in tool_names, f"Expected tool '{expected}' not found in {tool_names}"

def test_call_tool_execute_sql_read_only(self, dbsql_mcp_client, cached_dbsql_tools_list):
"""execute_sql_read_only with SHOW CATALOGS should return results."""
result = dbsql_mcp_client.call_tool("execute_sql_read_only", {"query": "SHOW CATALOGS"})
assert isinstance(result, CallToolResult)
assert result.content, "SHOW CATALOGS should return content"
assert len(result.content) > 0


# =============================================================================
# Raw streamable_http_client
# =============================================================================


@pytest.mark.integration
class TestRawStreamableHttpClient:
"""Verify DatabricksOAuthClientProvider works with the raw MCP SDK streamable_http_client.

This tests the low-level path: httpx.AsyncClient + DatabricksOAuthClientProvider
+ streamable_http_client + ClientSession, without going through DatabricksMCPClient.
"""

@pytest.mark.asyncio
async def test_uc_function_list_and_call(self, uc_function_url, workspace_client):
"""list_tools + call_tool via raw streamable_http_client for UC functions."""
async with raw_mcp_session(uc_function_url, workspace_client) as session:
tools_response = await session.list_tools()
tools = tools_response.tools
assert len(tools) > 0
tool_names = [t.name for t in tools]
assert any("echo_message" in name for name in tool_names)

tool_name = next(n for n in tool_names if "echo_message" in n)
result = await session.call_tool(tool_name, {"message": "raw_client_test"})
assert result.content
first = result.content[0]
assert hasattr(first, "text")
assert "raw_client_test" in str(first.text)

@pytest.mark.asyncio
async def test_vs_list_tools(self, vs_mcp_url, workspace_client):
"""list_tools via raw streamable_http_client for Vector Search."""
async with raw_mcp_session(vs_mcp_url, workspace_client) as session:
tools_response = await session.list_tools()
assert len(tools_response.tools) > 0

@pytest.mark.asyncio
async def test_dbsql_list_and_call(self, dbsql_mcp_url, workspace_client):
"""list_tools + call_tool via raw streamable_http_client for DBSQL."""
async with raw_mcp_session(dbsql_mcp_url, workspace_client) as session:
tools_response = await session.list_tools()
tools = tools_response.tools
tool_names = [t.name for t in tools]
assert "execute_sql_read_only" in tool_names

result = await session.call_tool("execute_sql_read_only", {"query": "SHOW CATALOGS"})
assert result.content
assert len(result.content) > 0

@pytest.mark.asyncio
async def test_genie_list_and_call(self, genie_mcp_url, workspace_client):
"""list_tools + call_tool via raw streamable_http_client for Genie."""
async with raw_mcp_session(genie_mcp_url, workspace_client) as session:
tools_response = await session.list_tools()
tools = tools_response.tools
assert len(tools) > 0

tool = tools[0]
properties = tool.inputSchema.get("properties", {})
param_name = next(iter(properties), "query")
result = await session.call_tool(tool.name, {param_name: "How many rows are there?"})
assert result.content
assert len(result.content) > 0


# =============================================================================
# Error paths
# =============================================================================
Expand Down
Loading
Loading