search_skills
This commit is contained in:
@@ -35,12 +35,23 @@ class TestMcpHttpEndpoints:
|
||||
"""Covers MCP transport endpoint smoke behavior."""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_exposes_no_tools(self, mcp_session_factory) -> None:
|
||||
"""Ensures the server publishes only native resource and prompt surfaces."""
|
||||
async def test_tools_bridge_native_skill_resources(self, mcp_session_factory) -> None:
|
||||
"""Ensures tool-only clients can discover and read native skill resources."""
|
||||
async with mcp_session_factory() as mcp_session:
|
||||
result = await mcp_session.list_tools()
|
||||
tools_result = await mcp_session.list_tools()
|
||||
list_result = await mcp_session.call_tool("list_resources")
|
||||
read_result = await mcp_session.call_tool(
|
||||
"read_resource",
|
||||
{"uri": "skill://mcp-details/SKILL.md"},
|
||||
)
|
||||
|
||||
assert result.tools == []
|
||||
assert {tool.name for tool in tools_result.tools} == {
|
||||
"list_resources",
|
||||
"read_resource",
|
||||
"search_skills",
|
||||
}
|
||||
assert "skill://mcp-details/SKILL.md" in list_result.content[0].text
|
||||
assert "# MCP Details" in read_result.content[0].text
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_accepts_initialize_jsonrpc_request(
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
from mcp.types import PromptReference
|
||||
|
||||
pytestmark = pytest.mark.smoke
|
||||
|
||||
@@ -18,6 +19,21 @@ EXPECTED_PROMPTS = {
|
||||
class TestMcpPromptSurface:
|
||||
"""Covers smoke-level MCP prompt discovery and retrieval paths."""
|
||||
|
||||
class TestServerMetadata:
|
||||
"""Covers client-facing identity and completion capabilities."""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_advertises_instructions_and_completions(self, mcp_session_factory) -> None:
|
||||
"""Ensures VS Code receives server guidance and completion support."""
|
||||
async with mcp_session_factory(initialize=False) as mcp_session:
|
||||
result = await mcp_session.initialize()
|
||||
|
||||
assert result.instructions is not None
|
||||
assert "skill://<name>/SKILL.md" in result.instructions
|
||||
assert result.server_info.icons
|
||||
assert result.server_info.icons[0].src.startswith("data:image/svg+xml;base64,")
|
||||
assert result.capabilities.completions is not None
|
||||
|
||||
class TestPromptDiscovery:
|
||||
"""Covers MCP prompts/list behavior using native prompt objects."""
|
||||
|
||||
@@ -29,6 +45,18 @@ class TestMcpPromptSurface:
|
||||
|
||||
assert {prompt.name for prompt in result.prompts} == EXPECTED_PROMPTS
|
||||
assert all(prompt.description for prompt in result.prompts)
|
||||
assert all(prompt.title for prompt in result.prompts)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_completes_authored_prompt_choices(self, mcp_session_factory) -> None:
|
||||
"""Ensures finite prompt choices are available as IDE-style suggestions."""
|
||||
async with mcp_session_factory() as mcp_session:
|
||||
result = await mcp_session.complete(
|
||||
PromptReference(type="ref/prompt", name="authoring"),
|
||||
{"name": "artifact_type", "value": "pr"},
|
||||
)
|
||||
|
||||
assert result.completion.values == ["prompt"]
|
||||
|
||||
class TestPromptResolution:
|
||||
"""Covers MCP prompts/get behavior using native request and response objects."""
|
||||
|
||||
@@ -10,6 +10,50 @@ pytestmark = pytest.mark.smoke
|
||||
class TestMcpSkillsSurface:
|
||||
"""Covers native skill resources over the HTTP MCP surface."""
|
||||
|
||||
class TestCompatibilityTools:
|
||||
"""Covers metadata for tool-only MCP clients."""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_exposes_safe_human_readable_tools(self, mcp_session_factory) -> None:
|
||||
"""Ensures clients receive display titles and complete safety hints."""
|
||||
async with mcp_session_factory() as mcp_session:
|
||||
result = await mcp_session.list_tools()
|
||||
|
||||
tools = {tool.name: tool for tool in result.tools}
|
||||
assert tools["search_skills"].title == "Search Skills"
|
||||
assert tools["list_resources"].title == "List Resources"
|
||||
assert tools["read_resource"].title == "Read Resource"
|
||||
assert all(tool.annotations is not None for tool in tools.values())
|
||||
assert all(tool.annotations.read_only_hint for tool in tools.values() if tool.annotations is not None)
|
||||
assert all(tool.annotations.idempotent_hint for tool in tools.values() if tool.annotations is not None)
|
||||
assert all(
|
||||
tool.annotations.open_world_hint is False for tool in tools.values() if tool.annotations is not None
|
||||
)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_searches_skill_metadata_without_loading_content(self, mcp_session_factory) -> None:
|
||||
"""Ensures search returns bounded canonical skill pointers ranked by metadata."""
|
||||
async with mcp_session_factory() as mcp_session:
|
||||
result = await mcp_session.call_tool(
|
||||
"search_skills",
|
||||
{"query": "FastMCP protocol", "limit": 1},
|
||||
)
|
||||
|
||||
assert result.is_error is False
|
||||
assert result.structured_content == {
|
||||
"results": [
|
||||
{
|
||||
"name": "mcp-details",
|
||||
"description": (
|
||||
"Reference hub for MCP and FastMCP source documentation links. Use when you need "
|
||||
"authoritative protocol, SDK, transport, and deployment docs without loading broad "
|
||||
"implementation guidance."
|
||||
),
|
||||
"uri": "skill://mcp-details/SKILL.md",
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
class TestResources:
|
||||
"""Covers native skill resources, manifests, and file templates."""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user