@@ -179,6 +179,20 @@ async def mutating_list(ctx: ServerRequestContext[Any, Any], params: ListSkillsP
179179 assert exc_info .value .code == INTERNAL_ERROR
180180
181181
182+ async def test_skills_list_sends_skill_meta_as_underscore_meta () -> None :
183+ """ext-skills#157: a skill's optional metadata crosses the wire as `_meta`, not `meta`."""
184+
185+ async def with_meta (ctx : ServerRequestContext [Any , Any ], params : ListSkillsParams ) -> ListSkillsResult :
186+ skill = _git_workflow_skill ().model_copy (update = {"meta" : {"example.com/owner" : "platform" }})
187+ return ListSkillsResult (skills = [skill ])
188+
189+ server = MCPServer ("catalog" , extensions = [Skills (list_skills = with_meta , get_skill = _get_skill )])
190+ async with Client (server , mode = "2026-07-28" ) as client :
191+ raw = await client .session .send_request (ListSkillsRequest (), _RawResult )
192+ extra = raw .model_extra or {}
193+ assert extra ["skills" ][0 ]["_meta" ] == {"example.com/owner" : "platform" }
194+
195+
182196async def test_skills_get_returns_the_matching_skill () -> None :
183197 async with Client (_server ()) as client :
184198 result = await client .session .send_request (
@@ -321,6 +335,28 @@ async def test_directory_read_returns_the_handlers_children() -> None:
321335 assert [r .uri for r in result .resources ] == ["skill://git-workflow/references" ]
322336
323337
338+ async def test_directory_read_defaults_to_private_cache_scope_on_the_2026_07_28_wire () -> None :
339+ """ext-skills#157: `resources/directory/read` results carry SEP-2549's cache fields too."""
340+ async with Client (_server (with_directory_read = True ), mode = "2026-07-28" ) as client :
341+ raw = await client .session .send_request (
342+ ReadDirectoryRequest (params = ReadDirectoryParams (uri = "skill://git-workflow" )), _RawResult
343+ )
344+ extra = raw .model_extra or {}
345+ assert (extra ["ttlMs" ], extra ["cacheScope" ]) == (0 , "private" )
346+
347+
348+ async def test_directory_read_omits_cache_fields_on_a_legacy_wire () -> None :
349+ """SEP-2549 fields are 2026-07-28+ only, and the runner's sieve skips extension methods,
350+ so `Skills` strips them itself for an older connection."""
351+ async with Client (_server (with_directory_read = True ), mode = "legacy" ) as client :
352+ raw = await client .session .send_request (
353+ ReadDirectoryRequest (params = ReadDirectoryParams (uri = "skill://git-workflow" )), _RawResult
354+ )
355+ extra = raw .model_extra or {}
356+ assert "cacheScope" not in extra
357+ assert "ttlMs" not in extra
358+
359+
324360async def test_directory_read_is_not_registered_without_a_handler () -> None :
325361 """SDK-defined: omitting `read_directory` doesn't just skip the capability ad - the
326362 method itself isn't registered, so calling it anyway is Method not found."""
0 commit comments