From 1060c9f426ea85e6af2f51445cb2b684db0fbfca Mon Sep 17 00:00:00 2001 From: aravind-segu Date: Wed, 21 Jan 2026 15:53:44 -0800 Subject: [PATCH 1/4] Fix Local Execution of MCP Servers --- mcp-server-hello-world/README.md | 12 +- mcp-server-hello-world/pyproject.toml | 1 + mcp-server-hello-world/scripts/dev/README.md | 10 +- .../scripts/dev/query_local.py | 106 ++++++++++++++++++ .../tests/test_integration_server.py | 34 +++--- mcp-server-open-api-spec/pyproject.toml | 3 +- .../tests/test_integration_server.py | 42 +++++-- 7 files changed, 166 insertions(+), 42 deletions(-) create mode 100644 mcp-server-hello-world/scripts/dev/query_local.py diff --git a/mcp-server-hello-world/README.md b/mcp-server-hello-world/README.md index 01e0b68c..7e154964 100644 --- a/mcp-server-hello-world/README.md +++ b/mcp-server-hello-world/README.md @@ -119,17 +119,11 @@ uv run pytest tests/ ```bash ./scripts/dev/start_server.sh ``` - -```python -from databricks_mcp import DatabricksMCPClient -mcp_client = DatabricksMCPClient( - server_url="http://localhost:8000" -) -# List available MCP tools -print(mcp_client.list_tools()) +```bash +python ./scripts/dev/query_local.py ``` -The script connects to your local MCP server without authentication and lists available tools. +With the server running you can run the `query_local.py` file to test the server locally. `query_local.py` lists and returns all the available tools. Uncomment code as necessary in the script to call an individual tool. #### End-to-end test your deployed MCP server diff --git a/mcp-server-hello-world/pyproject.toml b/mcp-server-hello-world/pyproject.toml index e11cae13..bfa45c0f 100644 --- a/mcp-server-hello-world/pyproject.toml +++ b/mcp-server-hello-world/pyproject.toml @@ -26,6 +26,7 @@ dev = [ "databricks-sdk", "databricks-mcp", "pytest", + "pytest-asyncio", "requests" ] diff --git a/mcp-server-hello-world/scripts/dev/README.md b/mcp-server-hello-world/scripts/dev/README.md index c2361da3..3482d1bd 100644 --- a/mcp-server-hello-world/scripts/dev/README.md +++ b/mcp-server-hello-world/scripts/dev/README.md @@ -17,13 +17,9 @@ Scripts for testing and developing the MCP server. ./scripts/dev/start_server.sh # Terminal 1 ``` -```python -from databricks_mcp import DatabricksMCPClient -mcp_client = DatabricksMCPClient( - server_url="http://localhost:8000" -) -# List available MCP tools -print(mcp_client.list_tools()) +With the server running you can run the `query_local.py` file to test the server locally. `query_local.py` lists and returns all the available tools. Uncomment code as necessary in the script to call an individual tool. +```bash +python query_local.py # Terminal 2 ``` ### Remote Testing diff --git a/mcp-server-hello-world/scripts/dev/query_local.py b/mcp-server-hello-world/scripts/dev/query_local.py new file mode 100644 index 00000000..65270bd0 --- /dev/null +++ b/mcp-server-hello-world/scripts/dev/query_local.py @@ -0,0 +1,106 @@ +""" +Minimal example showing how to interact with an MCP server using Python. + +This script demonstrates: +1. Listing available tools +2. Calling a specific tool + +Requirements: + pip install mcp +""" + +import asyncio +import json +from typing import Any, List + +from mcp.client.session import ClientSession +from mcp.client.streamable_http import streamablehttp_client +from mcp.types import CallToolResult, Tool + +# --------------------------------------------------------------------- +# Configuration +# --------------------------------------------------------------------- + +SERVER_URL = "http://localhost:8000/mcp" # Update to your MCP server URL + + +# --------------------------------------------------------------------- +# MCP helpers +# --------------------------------------------------------------------- + + +async def list_tools() -> List[Tool]: + """ + Fetch and return the list of tools exposed by the MCP server. + """ + async with streamablehttp_client(url=SERVER_URL) as ( + read_stream, + write_stream, + _, + ): + async with ClientSession(read_stream, write_stream) as session: + await session.initialize() + return (await session.list_tools()).tools + + +async def call_tool( + tool_name: str, + arguments: dict[str, Any] | None = None, +) -> CallToolResult: + """ + Call a tool by name with optional arguments. + """ + async with streamablehttp_client(url=SERVER_URL) as ( + read_stream, + write_stream, + _, + ): + async with ClientSession(read_stream, write_stream) as session: + await session.initialize() + return await session.call_tool(tool_name, arguments) + + +# --------------------------------------------------------------------- +# Example usage +# --------------------------------------------------------------------- + + +async def main(): + print(f"Connecting to MCP server at {SERVER_URL} ...") + # List available tools + tools = await list_tools() + print(f"{len(tools)} tools found") + SEP = "-" * 80 + for tool in tools: + output = f""" +TOOL: {tool.name} +{SEP} +Description: +{tool.description.strip()} + +{SEP} +Input Schema: +{json.dumps(tool.inputSchema, indent=2)} + +{SEP} +Output Schema: +{json.dumps(tool.outputSchema, indent=2)} +{SEP} +{SEP} +""".strip() + print(output) + + # Example: call a tool + # Uncomment and update as needed + # + # result = await call_tool( + # tool_name="health", # Replace with the desired tool name + # arguments={}, # Replace with the desired arguments + # ) + # + # print("\nTool result:") + # print(result) + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/mcp-server-hello-world/tests/test_integration_server.py b/mcp-server-hello-world/tests/test_integration_server.py index f7472f22..5b198ac6 100644 --- a/mcp-server-hello-world/tests/test_integration_server.py +++ b/mcp-server-hello-world/tests/test_integration_server.py @@ -8,7 +8,8 @@ import pytest import requests -from databricks_mcp import DatabricksMCPClient +from mcp.client.session import ClientSession +from mcp.client.streamable_http import streamablehttp_client def _find_free_port() -> int: @@ -70,17 +71,20 @@ def run_mcp_server(): # Test List Tools runs without errors -def test_list_tools(run_mcp_server): - url = run_mcp_server - mcp_client = DatabricksMCPClient(server_url=f"{url}/mcp") - tools = mcp_client.list_tools() - - -# Test Call Tools runs without errors -def test_call_tools(run_mcp_server): - url = run_mcp_server - mcp_client = DatabricksMCPClient(server_url=f"{url}/mcp") - tools = mcp_client.list_tools() - for tool in tools: - result = mcp_client.call_tool(tool.name) - assert result is not None +@pytest.mark.asyncio +async def test_list_tools(run_mcp_server): + url = f"{run_mcp_server}/mcp" + async with streamablehttp_client(url=url) as ( + read_stream, + write_stream, + _, + ): + async with ClientSession(read_stream, write_stream) as session: + await session.initialize() + + response = await session.list_tools() + tools = response.tools + + assert tools is not None + assert isinstance(tools, list) + assert len(tools) > 0 diff --git a/mcp-server-open-api-spec/pyproject.toml b/mcp-server-open-api-spec/pyproject.toml index 9b1fef4f..bc458eaa 100644 --- a/mcp-server-open-api-spec/pyproject.toml +++ b/mcp-server-open-api-spec/pyproject.toml @@ -22,7 +22,8 @@ dev = [ "hatchling>=1.27.0", "ruff>=0.8.0", "databricks-mcp>=0.1.0", - "pytest" + "pytest", + "pytest-asyncio" ] [tool.hatch.build.targets.wheel] diff --git a/mcp-server-open-api-spec/tests/test_integration_server.py b/mcp-server-open-api-spec/tests/test_integration_server.py index bc4588a2..e2ddb971 100644 --- a/mcp-server-open-api-spec/tests/test_integration_server.py +++ b/mcp-server-open-api-spec/tests/test_integration_server.py @@ -8,7 +8,8 @@ import pytest import requests -from databricks_mcp import DatabricksMCPClient +from mcp.client.session import ClientSession +from mcp.client.streamable_http import streamablehttp_client def _find_free_port() -> int: @@ -85,15 +86,36 @@ def run_mcp_server(): # Test List Tools runs without errors -def test_list_tools(run_mcp_server): - url = run_mcp_server - mcp_client = DatabricksMCPClient(server_url=f"{url}/mcp") - tools = mcp_client.list_tools() +@pytest.mark.asyncio +async def test_list_tools(run_mcp_server): + url = f"{run_mcp_server}/mcp" + async with streamablehttp_client(url=url) as ( + read_stream, + write_stream, + _, + ): + async with ClientSession(read_stream, write_stream) as session: + await session.initialize() + + response = await session.list_tools() + tools = response.tools + + assert tools is not None + assert isinstance(tools, list) + assert len(tools) > 0 # Test Call Tools runs without errors -def test_call_tools(run_mcp_server): - url = run_mcp_server - mcp_client = DatabricksMCPClient(server_url=f"{url}/mcp") - result = mcp_client.call_tool("list_api_endpoints") - assert result is not None +@pytest.mark.asyncio +async def test_list_tools(run_mcp_server): + url = f"{run_mcp_server}/mcp" + async with streamablehttp_client(url=url) as ( + read_stream, + write_stream, + _, + ): + async with ClientSession(read_stream, write_stream) as session: + await session.initialize() + + response = await session.call_tool("list_api_endpoints") + assert response is not None From 2c5b3461949005e3f68466b2b0abd290ad69aada Mon Sep 17 00:00:00 2001 From: aravind-segu Date: Wed, 21 Jan 2026 16:20:38 -0800 Subject: [PATCH 2/4] update local --- mcp-server-open-api-spec/README.md | 6 +++++- mcp-server-open-api-spec/tests/test_integration_server.py | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/mcp-server-open-api-spec/README.md b/mcp-server-open-api-spec/README.md index cc8e139a..9ea17d99 100644 --- a/mcp-server-open-api-spec/README.md +++ b/mcp-server-open-api-spec/README.md @@ -129,7 +129,11 @@ uv sync - Start the server locally. Changes will trigger a reload: ```bash -uv run custom-server +DATABRICKS_CONFIG_PROFILE= \ +UC_CONNECTION_NAME= \ +SPEC_VOLUME_PATH= \ +SPEC_FILE_NAME= \ +uv run custom-open-api-spec-server ``` ## Testing diff --git a/mcp-server-open-api-spec/tests/test_integration_server.py b/mcp-server-open-api-spec/tests/test_integration_server.py index e2ddb971..727dfd84 100644 --- a/mcp-server-open-api-spec/tests/test_integration_server.py +++ b/mcp-server-open-api-spec/tests/test_integration_server.py @@ -107,7 +107,7 @@ async def test_list_tools(run_mcp_server): # Test Call Tools runs without errors @pytest.mark.asyncio -async def test_list_tools(run_mcp_server): +async def test_call_tools(run_mcp_server): url = f"{run_mcp_server}/mcp" async with streamablehttp_client(url=url) as ( read_stream, From e86000f3b7fede30aac6c4eaeb04ad704b12f880 Mon Sep 17 00:00:00 2001 From: aravind-segu Date: Wed, 28 Jan 2026 16:04:00 -0800 Subject: [PATCH 3/4] Address COmments --- mcp-server-hello-world/pyproject.toml | 1 + mcp-server-hello-world/scripts/dev/query_local.py | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/mcp-server-hello-world/pyproject.toml b/mcp-server-hello-world/pyproject.toml index bfa45c0f..5e1df0b6 100644 --- a/mcp-server-hello-world/pyproject.toml +++ b/mcp-server-hello-world/pyproject.toml @@ -38,6 +38,7 @@ dev = [ [project.scripts] custom-mcp-server = "server.main:main" +query-local = "scripts.dev.query_local:run_locally" [build-system] requires = ["hatchling"] diff --git a/mcp-server-hello-world/scripts/dev/query_local.py b/mcp-server-hello-world/scripts/dev/query_local.py index 65270bd0..fa64241f 100644 --- a/mcp-server-hello-world/scripts/dev/query_local.py +++ b/mcp-server-hello-world/scripts/dev/query_local.py @@ -102,5 +102,8 @@ async def main(): # print(result) -if __name__ == "__main__": +def run_locally(): asyncio.run(main()) + +if __name__ == "__main__": + run_locally() From 5203a0bab0db441d58c056c900b7780184dc9f19 Mon Sep 17 00:00:00 2001 From: aravind-segu Date: Wed, 28 Jan 2026 16:08:28 -0800 Subject: [PATCH 4/4] update readme --- mcp-server-hello-world/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mcp-server-hello-world/README.md b/mcp-server-hello-world/README.md index 7e154964..418c7556 100644 --- a/mcp-server-hello-world/README.md +++ b/mcp-server-hello-world/README.md @@ -120,7 +120,7 @@ uv run pytest tests/ ./scripts/dev/start_server.sh ``` ```bash -python ./scripts/dev/query_local.py +uv run query-local ``` With the server running you can run the `query_local.py` file to test the server locally. `query_local.py` lists and returns all the available tools. Uncomment code as necessary in the script to call an individual tool.