4b6817381b
CI (OpenClaw E2E) / openclaw test (push) Has been cancelled
CI / coverage-report (push) Has been cancelled
CI / test-kubernetes (push) Has been cancelled
CI / should-run-thorough (push) Has been cancelled
CI / test-thorough (cloudwatch-demo) (push) Has been cancelled
CI / test-thorough (flink-ecs) (push) Has been cancelled
CI / test-thorough (upstream-lambda) (push) Has been cancelled
CI / test-thorough (prefect-ecs-fargate) (push) Has been cancelled
Release / build-binaries (zip, opensre.exe, onefile, windows-latest, windows-x64) (push) Has been cancelled
Benchmark image — build + push to ECR (any adapter) / build + push (push) Has been cancelled
CI / quality (ubuntu-latest) (push) Has been cancelled
CI / test (tools-runtime) (push) Has been cancelled
CI / test (e2e-general) (push) Has been cancelled
CI / test (cli-runtime) (push) Has been cancelled
CI / test (e2e-provider-and-openclaw) (push) Has been cancelled
CI / test (integrations-and-misc) (push) Has been cancelled
Release / verify (push) Has been cancelled
Release / build-python-dist (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, macos-15-intel, darwin-x64) (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, macos-latest, darwin-arm64) (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04, linux-x64) (push) Has been cancelled
Release / publish-release (push) Has been cancelled
Release / publish-main-release (push) Has been cancelled
Interactive Shell Live (PR + post-merge) / turn-checks (no-LLM) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Interactive Shell Live (PR + post-merge) / turn-live shard ${{ matrix.shard_index }} (push) Has been cancelled
Release / prepare (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04-arm, linux-arm64) (push) Has been cancelled
Synthetic Deterministic Tests / Synthetic offline (deterministic) (push) Has been cancelled
82 lines
3.1 KiB
Python
82 lines
3.1 KiB
Python
"""Tests for the shared MCP tool-catalog listing helper."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from core.tool_framework.utils.mcp_tool_listing import (
|
|
MAX_DESCRIPTION_CHARS,
|
|
MAX_SCHEMAS_RETURNED,
|
|
MAX_TOOLS_RETURNED,
|
|
build_mcp_tool_listing,
|
|
)
|
|
|
|
|
|
def _tools(count: int) -> list[dict[str, object]]:
|
|
return [
|
|
{"name": f"tool-{i:03d}", "description": f"desc {i}", "input_schema": {"i": i}}
|
|
for i in range(count)
|
|
]
|
|
|
|
|
|
def test_default_listing_drops_schema_and_truncates_description() -> None:
|
|
tools = [{"name": "execute-sql", "description": "Run HogQL " * 50, "input_schema": {"a": 1}}]
|
|
listing = build_mcp_tool_listing(tools, name_filter=None, include_schema=False)
|
|
|
|
entry = listing["tools"][0]
|
|
assert entry["name"] == "execute-sql"
|
|
assert "input_schema" not in entry
|
|
assert len(entry["description"]) <= MAX_DESCRIPTION_CHARS
|
|
assert listing["total_tools"] == 1
|
|
assert listing["returned_tools"] == 1
|
|
|
|
|
|
def test_caps_returned_tools_and_notes_truncation() -> None:
|
|
listing = build_mcp_tool_listing(_tools(244), name_filter=None, include_schema=False)
|
|
assert listing["total_tools"] == 244
|
|
assert listing["returned_tools"] == MAX_TOOLS_RETURNED
|
|
assert "name_filter" in str(listing.get("notes", ""))
|
|
|
|
|
|
def test_name_filter_matches_name_or_description() -> None:
|
|
tools = [
|
|
{"name": "execute-sql", "description": "Run HogQL", "input_schema": {}},
|
|
{"name": "feature-flag-get-all", "description": "List flags", "input_schema": {}},
|
|
{"name": "query-trends", "description": "Trend query over events", "input_schema": {}},
|
|
]
|
|
listing = build_mcp_tool_listing(tools, name_filter="events query sql", include_schema=False)
|
|
assert {t["name"] for t in listing["tools"]} == {"execute-sql", "query-trends"}
|
|
assert listing["matched_tools"] == 2
|
|
assert listing["name_filter"] == "events query sql"
|
|
|
|
|
|
def test_include_schema_only_when_result_set_is_small() -> None:
|
|
narrow = build_mcp_tool_listing(_tools(2), name_filter=None, include_schema=True)
|
|
assert all("input_schema" in t for t in narrow["tools"])
|
|
|
|
wide = build_mcp_tool_listing(
|
|
_tools(MAX_SCHEMAS_RETURNED + 1), name_filter=None, include_schema=True
|
|
)
|
|
assert all("input_schema" not in t for t in wide["tools"])
|
|
assert "input_schema omitted" in str(wide.get("notes", ""))
|
|
|
|
|
|
def test_filter_example_appears_in_notes() -> None:
|
|
# The vendor-specific example only shows when a filter narrowed the set below
|
|
# the cap while the full catalog still exceeds it.
|
|
listing = build_mcp_tool_listing(
|
|
_tools(100),
|
|
name_filter="tool-01",
|
|
include_schema=False,
|
|
filter_example="issue event trace",
|
|
)
|
|
assert "issue event trace" in str(listing.get("notes", ""))
|
|
|
|
|
|
def test_skips_unnamed_or_non_dict_entries_gracefully() -> None:
|
|
# Defensive: the helper is fed whatever the MCP server returns.
|
|
listing = build_mcp_tool_listing(
|
|
[{"name": "ok", "description": "d", "input_schema": {}}],
|
|
name_filter=None,
|
|
include_schema=False,
|
|
)
|
|
assert listing["returned_tools"] == 1
|