From 5385556b66611cb2c6aec4775076dfc5e6a6da81 Mon Sep 17 00:00:00 2001 From: "lilong.129" Date: Fri, 25 Apr 2025 17:55:24 +0800 Subject: [PATCH] fix: mcp test json --- internal/mcp/config_test.go | 6 +- internal/mcp/hub_test.go | 23 ++----- internal/mcp/test.mcp.json | 37 ----------- internal/mcp/testdata/demo_weather.py | 94 +++++++++++++++++++++++++++ internal/mcp/testdata/test.mcp.json | 27 ++++++++ internal/version/VERSION | 2 +- server/ui_test.go | 2 +- 7 files changed, 130 insertions(+), 61 deletions(-) delete mode 100644 internal/mcp/test.mcp.json create mode 100644 internal/mcp/testdata/demo_weather.py create mode 100644 internal/mcp/testdata/test.mcp.json diff --git a/internal/mcp/config_test.go b/internal/mcp/config_test.go index d21c92db..e3942216 100644 --- a/internal/mcp/config_test.go +++ b/internal/mcp/config_test.go @@ -8,7 +8,7 @@ import ( func TestLoadSettings(t *testing.T) { // Load settings from test.mcp.json - settings, err := LoadSettings("test.mcp.json") + settings, err := LoadSettings("testdata/test.mcp.json") if err != nil { t.Fatalf("Failed to load settings: %v", err) } @@ -21,11 +21,11 @@ func TestLoadSettings(t *testing.T) { // Verify specific server configurations filesystemConfig := settings.MCPServers["filesystem"] assert.Equal(t, "npx", filesystemConfig.Command) - assert.Equal(t, []string{"-y", "@modelcontextprotocol/server-filesystem", "/Users/debugtalk/Downloads/tmp"}, filesystemConfig.Args) + assert.Equal(t, []string{"-y", "@modelcontextprotocol/server-filesystem", "/tmp"}, filesystemConfig.Args) weatherConfig := settings.MCPServers["weather"] assert.Equal(t, "uv", weatherConfig.Command) - assert.Equal(t, []string{"--directory", "/Users/debugtalk/MyProjects/ByteDance/EvalTools/quickstart-resources/weather-server-python/", "run", "weather.py"}, weatherConfig.Args) + assert.Equal(t, []string{"--directory", "/Users/debugtalk/MyProjects/HttpRunner-dev/httprunner/internal/mcp/testdata", "run", "demo_weather.py"}, weatherConfig.Args) assert.Equal(t, []string{"get_forecast"}, weatherConfig.AutoApprove) assert.Equal(t, map[string]string{"ABC": "123"}, weatherConfig.Env) } diff --git a/internal/mcp/hub_test.go b/internal/mcp/hub_test.go index d36b10cf..22ffd12e 100644 --- a/internal/mcp/hub_test.go +++ b/internal/mcp/hub_test.go @@ -14,7 +14,7 @@ import ( ) func TestGetTools(t *testing.T) { - hub, err := NewMCPHub("./test.mcp.json") + hub, err := NewMCPHub("./testdata/test.mcp.json") require.NoError(t, err) ctx := context.Background() @@ -27,7 +27,7 @@ func TestGetTools(t *testing.T) { } func TestCallTool(t *testing.T) { - hub, err := NewMCPHub("./test.mcp.json") + hub, err := NewMCPHub("./testdata/test.mcp.json") require.NoError(t, err) ctx := context.Background() @@ -39,26 +39,11 @@ func TestCallTool(t *testing.T) { ) require.NoError(t, err) - result, err = hub.InvokeTool(ctx, "shoots_ug_toolbox_utils_utils", "get_udid", - map[string]interface{}{}, - ) - require.NoError(t, err) - - result, err = hub.InvokeTool(ctx, "shoots_ug_toolbox_utils_utils", "is_login", - map[string]interface{}{}, - ) - require.NoError(t, err) - - result, err = hub.InvokeTool(ctx, "shoots_ug_toolbox_utils_utils", "login_app_account", - map[string]interface{}{"phone": "a12342038903", "password": "a123456"}, - ) - require.NoError(t, err) - t.Logf("Result: %v", result) } func TestCallEinoTool(t *testing.T) { - hub, err := NewMCPHub("./test.mcp.json") + hub, err := NewMCPHub("./testdata/test.mcp.json") require.NoError(t, err) ctx := context.Background() @@ -76,7 +61,7 @@ func TestCallEinoTool(t *testing.T) { } func TestConvertToolsToRecordsFromFile(t *testing.T) { - hub, err := NewMCPHub("./test.mcp.json") + hub, err := NewMCPHub("./testdata/test.mcp.json") require.NoError(t, err) ctx := context.Background() diff --git a/internal/mcp/test.mcp.json b/internal/mcp/test.mcp.json deleted file mode 100644 index 263a8a44..00000000 --- a/internal/mcp/test.mcp.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "mcpServers": { - "shoots_ug_toolbox_install_helper": { - "args": [ - "--directory", - "/Users/debugtalk/MyProjects/ByteDance/EvalTools/shoots-ug-box", - "run", - "install_helper.py" - ], - "command": "uv" - }, - "shoots_ug_toolbox_utils_utils": { - "args": [ - "--directory", - "/Users/debugtalk/MyProjects/ByteDance/EvalTools/shoots-ug-box", - "run", - "utils_utils.py" - ], - "command": "uv" - }, - "weather": { - "args": [ - "--directory", - "/Users/debugtalk/MyProjects/ByteDance/EvalTools/shoots-ug-box", - "run", - "demo_weather.py" - ], - "autoApprove": [ - "get_forecast" - ], - "command": "uv", - "env": { - "ABC": "123" - } - } - } -} \ No newline at end of file diff --git a/internal/mcp/testdata/demo_weather.py b/internal/mcp/testdata/demo_weather.py new file mode 100644 index 00000000..74a3015e --- /dev/null +++ b/internal/mcp/testdata/demo_weather.py @@ -0,0 +1,94 @@ +from typing import Any +import httpx +from mcp.server.fastmcp import FastMCP + +# Initialize FastMCP server +mcp = FastMCP("weather") + +# Constants +NWS_API_BASE = "https://api.weather.gov" +USER_AGENT = "weather-app/1.0" + +async def make_nws_request(url: str) -> dict[str, Any] | None: + """Make a request to the NWS API with proper error handling.""" + headers = { + "User-Agent": USER_AGENT, + "Accept": "application/geo+json" + } + async with httpx.AsyncClient() as client: + try: + response = await client.get(url, headers=headers, timeout=30.0) + response.raise_for_status() + return response.json() + except Exception: + return None + +def format_alert(feature: dict) -> str: + """Format an alert feature into a readable string.""" + props = feature["properties"] + return f""" +Event: {props.get('event', 'Unknown')} +Area: {props.get('areaDesc', 'Unknown')} +Severity: {props.get('severity', 'Unknown')} +Description: {props.get('description', 'No description available')} +Instructions: {props.get('instruction', 'No specific instructions provided')} +""" + +@mcp.tool() +async def get_alerts(state: str) -> str: + """Get weather alerts for a US state. + + Args: + state: Two-letter US state code (e.g. CA, NY) + """ + url = f"{NWS_API_BASE}/alerts/active/area/{state}" + data = await make_nws_request(url) + + if not data or "features" not in data: + return "Unable to fetch alerts or no alerts found." + + if not data["features"]: + return "No active alerts for this state." + + alerts = [format_alert(feature) for feature in data["features"]] + return "\n---\n".join(alerts) + +@mcp.tool() +async def get_forecast(latitude: float, longitude: float) -> str: + """Get weather forecast for a location. + + Args: + latitude: Latitude of the location + longitude: Longitude of the location + """ + # First get the forecast grid endpoint + points_url = f"{NWS_API_BASE}/points/{latitude},{longitude}" + points_data = await make_nws_request(points_url) + + if not points_data: + return "Unable to fetch forecast data for this location." + + # Get the forecast URL from the points response + forecast_url = points_data["properties"]["forecast"] + forecast_data = await make_nws_request(forecast_url) + + if not forecast_data: + return "Unable to fetch detailed forecast." + + # Format the periods into a readable forecast + periods = forecast_data["properties"]["periods"] + forecasts = [] + for period in periods[:5]: # Only show next 5 periods + forecast = f""" +{period['name']}: +Temperature: {period['temperature']}°{period['temperatureUnit']} +Wind: {period['windSpeed']} {period['windDirection']} +Forecast: {period['detailedForecast']} +""" + forecasts.append(forecast) + + return "\n---\n".join(forecasts) + +if __name__ == "__main__": + # Initialize and run the server + mcp.run(transport='stdio') diff --git a/internal/mcp/testdata/test.mcp.json b/internal/mcp/testdata/test.mcp.json new file mode 100644 index 00000000..26be6fb1 --- /dev/null +++ b/internal/mcp/testdata/test.mcp.json @@ -0,0 +1,27 @@ +{ + "mcpServers": { + "filesystem": { + "command": "npx", + "args": [ + "-y", + "@modelcontextprotocol/server-filesystem", + "/tmp" + ] + }, + "weather": { + "args": [ + "--directory", + "/Users/debugtalk/MyProjects/HttpRunner-dev/httprunner/internal/mcp/testdata", + "run", + "demo_weather.py" + ], + "autoApprove": [ + "get_forecast" + ], + "command": "uv", + "env": { + "ABC": "123" + } + } + } +} diff --git a/internal/version/VERSION b/internal/version/VERSION index 194c076c..cba4e290 100644 --- a/internal/version/VERSION +++ b/internal/version/VERSION @@ -1 +1 @@ -v5.0.0-beta-2504251727 +v5.0.0-beta-2504251755 diff --git a/server/ui_test.go b/server/ui_test.go index a84603e6..f39ded86 100644 --- a/server/ui_test.go +++ b/server/ui_test.go @@ -74,7 +74,7 @@ func TestTapHandler(t *testing.T) { func TestInvokeToolHandler(t *testing.T) { router := NewRouter() - router.InitMCPHub("../internal/mcp/test.mcp.json") + router.InitMCPHub("../internal/mcp/testdata/test.mcp.json") tests := []struct { name string