Skip to content

Commit c71635c

Browse files
Made SkillCatalog's public surface minimal
1 parent 18eece6 commit c71635c

2 files changed

Lines changed: 12 additions & 10 deletions

File tree

‎src/mcp/server/skills/catalog.py‎

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -109,13 +109,13 @@ def __init__(
109109
self,
110110
*,
111111
skills: Sequence[Skill],
112-
files: Mapping[str, _SkillFileResource],
112+
files: Mapping[str, Resource],
113113
directories: Mapping[str, Sequence[ResourceEntry]] | None,
114114
ttl_ms: int,
115115
cache_scope: Literal["public", "private"],
116116
page_size: int | None,
117117
) -> None:
118-
"""Assemble a catalog from already-validated parts; use `SkillCatalog.load()` instead.
118+
"""Assemble a catalog from already-validated parts. Use `SkillCatalog.load()`, which builds them.
119119
120120
Raises:
121121
ValidationError: If `ttl_ms` is negative.
@@ -232,11 +232,6 @@ async def load(
232232
page_size=page_size,
233233
)
234234

235-
@property
236-
def skills(self) -> Sequence[Skill]:
237-
"""The valid skills, sorted by URI."""
238-
return self._catalog_skills
239-
240235
def resources(self) -> Sequence[ResourceBinding]:
241236
"""One binding per served file, sorted by URI."""
242237
return [ResourceBinding(resource=file) for file in sorted(self._files.values(), key=lambda f: f.uri)]

‎tests/server/skills/test_catalog.py‎

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
ReadDirectoryParams,
4343
ReadDirectoryRequest,
4444
ReadDirectoryResult,
45+
Skill,
4546
)
4647

4748
pytestmark = pytest.mark.anyio
@@ -88,6 +89,12 @@ def _digest(data: bytes) -> str:
8889
return f"sha256:{hashlib.sha256(data).hexdigest()}"
8990

9091

92+
async def _listed(catalog: SkillCatalog) -> list[Skill]:
93+
server = MCPServer("skills", extensions=[catalog])
94+
async with Client(server, extensions=[ClientSkills()]) as client:
95+
return list(await client.extension(ClientSkills).list_skills())
96+
97+
9198
async def _server(files: Mapping[str, bytes], **options: Any) -> MCPServer:
9299
catalog = await SkillCatalog.load(_MemoryProvider(files), parse_frontmatter=_parse, **options)
93100
return MCPServer("skills", extensions=[catalog])
@@ -283,7 +290,7 @@ async def list_files(self) -> Sequence[str]:
283290
catalog = await SkillCatalog.load(
284291
GeneratorProvider({"git-workflow/SKILL.md": _skill_md("git-workflow")}), parse_frontmatter=_parse
285292
)
286-
assert [skill.uri for skill in catalog.skills] == ["skill://git-workflow/SKILL.md"]
293+
assert [skill.uri for skill in await _listed(catalog)] == ["skill://git-workflow/SKILL.md"]
287294

288295

289296
async def test_strict_load_raises_one_error_naming_every_invalid_skill() -> None:
@@ -345,7 +352,7 @@ def parse_with_date(text: str) -> Mapping[str, Any]:
345352
catalog = await SkillCatalog.load(
346353
_MemoryProvider({"git-workflow/SKILL.md": _skill_md("git-workflow")}), parse_frontmatter=parse_with_date
347354
)
348-
assert catalog.skills[0].frontmatter == {
355+
assert (await _listed(catalog))[0].frontmatter == {
349356
"name": "git-workflow",
350357
"description": "d",
351358
"released": "2026-07-28",
@@ -450,7 +457,7 @@ async def test_a_skill_over_the_recommended_limits_is_still_served_with_a_warnin
450457
with caplog.at_level(logging.WARNING, logger=CATALOG_LOGGER):
451458
catalog = await SkillCatalog.load(_MemoryProvider(files), parse_frontmatter=_parse)
452459

453-
assert [skill.uri for skill in catalog.skills] == ["skill://big/SKILL.md"]
460+
assert [skill.uri for skill in await _listed(catalog)] == ["skill://big/SKILL.md"]
454461
assert len([record for record in caplog.records if "skill://big/SKILL.md" in record.getMessage()]) == 2
455462

456463

0 commit comments

Comments
 (0)