"""MCP as the standard entry: the method travels, and describe fans out. Subagents inherit a session's MCP tools; they do not inherit its skills. So a working method that lives only in a skill reaches the main thread and no arm below it, and the one place it can reach every caller is the server's own `instructions` and tool descriptions -- both capped by Claude Code at 2 KB each, which is why what travels is the SHORT version and the long one stays in the skill. """ from __future__ import annotations import sys from pathlib import Path import pytest PROJECT_ROOT = Path(__file__).resolve().parents[1] sys.path.insert(0, str(PROJECT_ROOT / "src")) from llm_ingestion_okf import consume as okf_consume # noqa: E402 from llm_ingestion_okf import mcp_server, project # noqa: E402 GOLDEN = PROJECT_ROOT / "examples" / "ingest-golden-segmented-okf-v0-2" / "expected-bundle" FIXTURE = PROJECT_ROOT / "tests" / "fixtures" / "consume-bundle" #: Claude Code truncates server instructions and each tool description at 2 KB #: (`docs-en-mcp.md`). A description over it is not rejected -- it is CUT, which #: is worse: the reader gets the first half of a method and no sign that the #: rest existed. CLIENT_TRUNCATION_BYTES = 2048 @pytest.fixture def served(tmp_path: Path) -> mcp_server.Surface: root = tmp_path / "root" (root / "a").mkdir(parents=True) (root / "b").mkdir(parents=True) for name, source in (("a", GOLDEN), ("b", FIXTURE)): for path in source.rglob("*"): if path.is_file(): target = root / name / path.relative_to(source) target.parent.mkdir(parents=True, exist_ok=True) target.write_bytes(path.read_bytes()) return mcp_server.Surface(roots=(root,), fixed=None, profile=okf_consume.DEFAULT_PROFILE) def _instructions(surface: mcp_server.Surface) -> str: result = mcp_server.handle(surface, "initialize", {}) assert isinstance(result["instructions"], str) return result["instructions"] def test_the_instructions_carry_the_short_working_method(served: mcp_server.Surface) -> None: text = _instructions(served) for mark in ("bundle's own words", "sub-question", "ask again", "outside the cut"): assert mark in text, f"the instructions do not say {mark!r}" def test_the_instructions_fit_inside_what_the_client_keeps( served: mcp_server.Surface, ) -> None: text = _instructions(served) assert len(text.encode("utf-8")) <= CLIENT_TRUNCATION_BYTES # The control: the limit is one this text could realistically cross, so # the assertion above is a measurement and not a tautology. assert len(text.encode("utf-8")) > CLIENT_TRUNCATION_BYTES // 4 def test_every_tool_description_fits_and_the_asking_one_carries_the_method( served: mcp_server.Surface, ) -> None: by_name = {tool.name: tool for tool in mcp_server.tools(served)} for name, tool in by_name.items(): assert len(tool.description.encode("utf-8")) <= CLIENT_TRUNCATION_BYTES, name assert "ask again" in by_name["okf_ask"].description assert "withheld" in by_name["okf_ask"].description def test_describe_without_a_bundle_id_answers_for_every_served_bundle( served: mcp_server.Surface, ) -> None: """It refused instead, where `okf_ask` in the same position fans out. A tool that refuses the call a sibling tool accepts is a shape a client has to learn out of band, which is the configuration this server exists to remove. """ result = mcp_server.call_describe(served, {}) assert sorted(result["asked"]) == ["b-golden-segmented-okf-v0-2", "consume-fixture"] cards = result["cards"] assert isinstance(cards, list) and len(cards) == 2 assert sorted(str(card["bundle_id"]) for card in cards) == sorted(result["asked"]) def test_describe_with_a_bundle_id_is_the_card_it_always_was( served: mcp_server.Surface, ) -> None: named = mcp_server.call_describe(served, {"bundle_id": "consume-fixture"}) assert named["bundle_id"] == "consume-fixture" assert "cards" not in named def test_a_one_to_one_server_still_answers_with_its_own_card(tmp_path: Path) -> None: surface = mcp_server.Surface( roots=(GOLDEN,), fixed="b-golden-segmented-okf-v0-2", profile=okf_consume.DEFAULT_PROFILE ) assert mcp_server.call_describe(surface, {})["bundle_id"] == "b-golden-segmented-okf-v0-2" def test_the_ask_answer_carries_the_compact_withheld_block( served: mcp_server.Surface, ) -> None: """A2 reaches the MCP arm because the payload is the payload.""" result = mcp_server.call_ask(served, {"question": "Hva sier veiledningen om krav?"}) for answer in result["answers"]: block = answer["payload"]["withheld"] assert set(block) == {"total", "by_rule", "nearest", "complete"} def test_the_readme_carries_the_one_line_that_registers_the_server() -> None: """The user runs it. This package never starts Claude Code.""" readme = (PROJECT_ROOT / "README.md").read_text(encoding="utf-8") assert "claude mcp add --scope user okf -- okf mcp --root" in readme def test_the_project_summary_says_what_to_do_next_with_the_server(tmp_path: Path) -> None: folder = tmp_path / "Dokumenter" folder.mkdir() (folder / "krav.md").write_text( "## 4 Grunnforhold\n\nGrunnen er morene over berg.\n", encoding="utf-8", newline="" ) _, _, summary = project.create(folder, out=tmp_path / "project") assert "claude mcp add --scope user okf -- okf mcp --root" in summary def test_a_project_bundle_is_where_a_root_server_finds_it(tmp_path: Path) -> None: """`--root ` must reach `/.okf/`. Measured rather than reasoned: the walk is bounded at `MAX_DISCOVERY_DEPTH`, and `.okf` spends one level of it. """ projects = tmp_path / "okf" folder = projects / "Mitt Prosjekt" / "kilder" folder.mkdir(parents=True) (folder / "krav.md").write_text( "## 4 Grunnforhold\n\nGrunnen er morene over berg.\n", encoding="utf-8", newline="" ) project.create(folder, out=projects / "Mitt Prosjekt", bundle_id="mitt-prosjekt") found = mcp_server.discover((projects,)) assert [served.bundle_id for served in found.bundles] == ["mitt-prosjekt"] def test_the_skill_command_refuses_a_missing_out_in_its_own_form(tmp_path: Path) -> None: """A5: exit 2 was already right; the TEXT was argparse's, not okf's. Every other refusal in this chain reads `refused (): `, and a caller parsing that form got one line that did not match on the one flag everybody forgets. The code stays 2 -- "the run did not happen" -- because that is what it is. """ import subprocess result = subprocess.run( [sys.executable, "-m", "llm_ingestion_okf.cli", "skill"], capture_output=True, text=True, check=False, cwd=PROJECT_ROOT, ) assert result.returncode == 2 assert "refused (out_missing)" in result.stderr assert "--out" in result.stderr