Skip to main content
Glama

Blockscout MCP Server

Official
test_direct_api_call.py7.92 kB
from unittest.mock import AsyncMock, MagicMock, patch import pytest from blockscout_mcp_server.models import DirectApiData, ToolResponse from blockscout_mcp_server.tools.direct_api.direct_api_call import direct_api_call @pytest.mark.asyncio async def test_direct_api_call_no_params(mock_ctx): chain_id = "1" endpoint_path = "/api/v2/stats" mock_base_url = "https://eth.blockscout.com" mock_response = {"result": 1} with ( patch( "blockscout_mcp_server.tools.direct_api.direct_api_call.get_blockscout_base_url", new_callable=AsyncMock, ) as mock_get_url, patch( "blockscout_mcp_server.tools.direct_api.direct_api_call.make_blockscout_request", new_callable=AsyncMock, ) as mock_request, ): mock_get_url.return_value = mock_base_url mock_request.return_value = mock_response result = await direct_api_call(chain_id=chain_id, endpoint_path=endpoint_path, ctx=mock_ctx) mock_get_url.assert_called_once_with(chain_id) mock_request.assert_called_once_with(base_url=mock_base_url, api_path=endpoint_path, params={}) assert isinstance(result, ToolResponse) assert isinstance(result.data, DirectApiData) assert result.data.model_dump() == mock_response assert result.pagination is None assert mock_ctx.report_progress.await_count == 3 @pytest.mark.asyncio async def test_direct_api_call_with_query_params_and_cursor(mock_ctx): chain_id = "1" endpoint_path = "/api/v2/foo" mock_base_url = "https://eth.blockscout.com" mock_response = {"data": []} query_params = {"limit": "1"} with ( patch( "blockscout_mcp_server.tools.direct_api.direct_api_call.get_blockscout_base_url", new_callable=AsyncMock, ) as mock_get_url, patch( "blockscout_mcp_server.tools.direct_api.direct_api_call.make_blockscout_request", new_callable=AsyncMock, ) as mock_request, patch( "blockscout_mcp_server.tools.direct_api.direct_api_call.apply_cursor_to_params", new_callable=MagicMock, ) as mock_apply_cursor, ): mock_get_url.return_value = mock_base_url mock_request.return_value = mock_response # Simulate cursor application updating params and assert inputs def fake_apply(cursor, params): assert cursor == "abc" assert params == {"limit": "1"} params.update({"page": 2}) mock_apply_cursor.side_effect = fake_apply result = await direct_api_call( chain_id=chain_id, endpoint_path=endpoint_path, ctx=mock_ctx, query_params=query_params, cursor="abc", ) mock_get_url.assert_called_once_with(chain_id) mock_apply_cursor.assert_called_once() mock_request.assert_called_once_with( base_url=mock_base_url, api_path=endpoint_path, params={"limit": "1", "page": 2}, ) assert isinstance(result, ToolResponse) assert isinstance(result.data, DirectApiData) assert result.data.model_dump() == mock_response assert result.pagination is None assert mock_ctx.report_progress.await_count == 3 @pytest.mark.asyncio async def test_direct_api_call_with_pagination(mock_ctx): chain_id = "1" endpoint_path = "/api/v2/data" mock_base_url = "https://eth.blockscout.com" mock_response = {"next_page_params": {"cursor": 123}, "items": []} with ( patch( "blockscout_mcp_server.tools.direct_api.direct_api_call.get_blockscout_base_url", new_callable=AsyncMock, ) as mock_get_url, patch( "blockscout_mcp_server.tools.direct_api.direct_api_call.make_blockscout_request", new_callable=AsyncMock, ) as mock_request, ): mock_get_url.return_value = mock_base_url mock_request.return_value = mock_response result = await direct_api_call(chain_id=chain_id, endpoint_path=endpoint_path, ctx=mock_ctx) assert isinstance(result, ToolResponse) assert result.pagination is not None assert result.pagination.next_call.tool_name == "direct_api_call" nc = result.pagination.next_call.params assert nc["chain_id"] == chain_id assert nc["endpoint_path"] == endpoint_path assert "cursor" in nc assert "query_params" not in nc mock_get_url.assert_called_once_with(chain_id) mock_request.assert_called_once_with(base_url=mock_base_url, api_path=endpoint_path, params={}) assert mock_ctx.report_progress.await_count == 3 @pytest.mark.asyncio async def test_direct_api_call_with_query_params_pagination(mock_ctx): chain_id = "1" endpoint_path = "/api/v2/data" query_params = {"sender": "0xabc"} mock_base_url = "https://eth.blockscout.com" mock_response = {"next_page_params": {"cursor": 456}, "items": []} with ( patch( "blockscout_mcp_server.tools.direct_api.direct_api_call.get_blockscout_base_url", new_callable=AsyncMock, ) as mock_get_url, patch( "blockscout_mcp_server.tools.direct_api.direct_api_call.make_blockscout_request", new_callable=AsyncMock, ) as mock_request, ): mock_get_url.return_value = mock_base_url mock_request.return_value = mock_response result = await direct_api_call( chain_id=chain_id, endpoint_path=endpoint_path, query_params=query_params, ctx=mock_ctx, ) assert isinstance(result, ToolResponse) assert result.pagination is not None nc = result.pagination.next_call.params assert nc["chain_id"] == chain_id assert nc["endpoint_path"] == endpoint_path assert nc["query_params"] == query_params assert "cursor" in nc mock_get_url.assert_called_once_with(chain_id) mock_request.assert_called_once_with(base_url=mock_base_url, api_path=endpoint_path, params=query_params) assert mock_ctx.report_progress.await_count == 3 @pytest.mark.asyncio async def test_direct_api_call_raises_on_request_error(mock_ctx): chain_id = "1" endpoint_path = "/api/v2/data" mock_base_url = "https://eth.blockscout.com" with ( patch( "blockscout_mcp_server.tools.direct_api.direct_api_call.get_blockscout_base_url", new_callable=AsyncMock, ) as mock_get_url, patch( "blockscout_mcp_server.tools.direct_api.direct_api_call.make_blockscout_request", new_callable=AsyncMock, ) as mock_request, ): mock_get_url.return_value = mock_base_url mock_request.side_effect = TimeoutError("upstream timeout") with pytest.raises(TimeoutError): await direct_api_call(chain_id=chain_id, endpoint_path=endpoint_path, ctx=mock_ctx) mock_get_url.assert_called_once_with(chain_id) mock_request.assert_awaited_once() assert mock_ctx.report_progress.await_count == 2 @pytest.mark.asyncio async def test_direct_api_call_rejects_query_in_path(mock_ctx): chain_id = "1" endpoint_path = "/api/v2/data?foo=bar" mock_base_url = "https://eth.blockscout.com" with ( patch( "blockscout_mcp_server.tools.direct_api.direct_api_call.get_blockscout_base_url", new_callable=AsyncMock, ) as mock_get_url, ): mock_get_url.return_value = mock_base_url with pytest.raises(ValueError): await direct_api_call(chain_id=chain_id, endpoint_path=endpoint_path, ctx=mock_ctx) mock_get_url.assert_called_once_with(chain_id) assert mock_ctx.report_progress.await_count == 1

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/blockscout/mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server