Fix skills frontmatter descriptions being YAML-typed instead of preserved

yaml.safe_load uses YAML 1.1, where bare words like `yes`/`no`/`on`/`off`
and numeric-looking scalars resolve to non-str Python values. Stringifying
that coerced value (e.g. `description: yes` -> "True") lost the author's
original text. Recover it via the existing line-based parser instead.
This commit is contained in:
Vishnu Jayavel 2026-07-29 16:53:33 -07:00
commit 0310ba6c7d
2 changed files with 41 additions and 3 deletions

View file

@ -104,7 +104,13 @@ def parse_frontmatter(content: str) -> tuple[dict[str, Any], str]:
# YAML may type `description: true` / dates as non-str, but SkillInfo.description
# is a str field that callers truthiness-check.
if "description" in parsed and parsed["description"] is not None:
parsed["description"] = str(parsed["description"])
if not isinstance(parsed["description"], str):
# YAML 1.1 coerces bare words like `yes` to non-str; recover the
# original text via the line-based parser instead.
raw = _parse_frontmatter_line_based(frontmatter_text).get("description")
parsed["description"] = (
raw if isinstance(raw, str) else str(parsed["description"])
)
return parsed, remaining

View file

@ -152,7 +152,7 @@ Body
assert frontmatter["enabled"] is True
assert isinstance(frontmatter["enabled"], bool)
def test_frontmatter_description_bool_coerced_to_str(self):
def test_frontmatter_description_bool_recovers_original_text(self):
content = """---
description: true
---
@ -160,9 +160,41 @@ description: true
Body
"""
frontmatter, body = parse_frontmatter(content)
assert frontmatter["description"] == "True"
assert frontmatter["description"] == "true"
assert isinstance(frontmatter["description"], str)
def test_frontmatter_description_yes_not_coerced_to_true(self):
# FastMCP #4416 regression: `yes` bare word previously coerced to True.
content = """---
description: yes
---
Body
"""
frontmatter, body = parse_frontmatter(content)
assert frontmatter["description"] == "yes"
def test_frontmatter_description_no_not_coerced_to_false(self):
content = """---
description: no
---
Body
"""
frontmatter, body = parse_frontmatter(content)
assert frontmatter["description"] == "no"
def test_frontmatter_description_numeric_scalar_preserves_original_text(self):
# YAML resolves `1.10` to float 1.1, dropping the trailing zero the author wrote.
content = """---
description: 1.10
---
Body
"""
frontmatter, body = parse_frontmatter(content)
assert frontmatter["description"] == "1.10"
class TestSkillProvider:
"""Tests for SkillProvider - single skill folder."""