"""Tests for T05 — MCP server (FR-1000). MCP tool functions are tested by calling them directly (the MCP registration is decorative — the logic lives in the function bodies). """ from __future__ import annotations import base64 import textwrap import markidocx.mcp_server as mcp_module from markidocx import __version__ SIMPLE_MANIFEST = textwrap.dedent("""\ project: name: "Test Document" feature_level: level1 family: article sources: - path: doc.md output: dir: ./dist """) SIMPLE_MARKDOWN = textwrap.dedent("""\ # Hello World A paragraph with **bold** text. ## Section - Item one - Item two """) # --------------------------------------------------------------------------- # get_version (FR-1010) # --------------------------------------------------------------------------- def test_get_version() -> None: result = mcp_module.get_version() assert result["version"] == __version__ # --------------------------------------------------------------------------- # list_templates (FR-1002) # --------------------------------------------------------------------------- def test_list_templates_returns_built_ins() -> None: families = mcp_module.list_templates() names = {f["name"] for f in families} assert "article" in names assert "book" in names assert "website" in names def test_list_templates_have_name_and_description() -> None: for f in mcp_module.list_templates(): assert "name" in f assert "description" in f # --------------------------------------------------------------------------- # list_styles (FR-1003) # --------------------------------------------------------------------------- def test_list_styles_returns_list() -> None: assert isinstance(mcp_module.list_styles(), list) # --------------------------------------------------------------------------- # validate_project (FR-1004) # --------------------------------------------------------------------------- def test_validate_project_ok() -> None: result = mcp_module.validate_project(SIMPLE_MANIFEST) assert result["status"] == "ok" assert result["project"] == "Test Document" assert result["family"] == "article" assert result["feature_level"] == "level1" def test_validate_project_error() -> None: bad = "project:\n name: x\n" result = mcp_module.validate_project(bad) assert result["status"] == "error" assert result["errors"] def test_validate_project_context_has_capabilities() -> None: result = mcp_module.validate_project(SIMPLE_MANIFEST) assert "supported_families" in result["context"] assert "supported_feature_levels" in result["context"] # --------------------------------------------------------------------------- # inspect_project (FR-1005) # --------------------------------------------------------------------------- def test_inspect_project_same_as_validate() -> None: v = mcp_module.validate_project(SIMPLE_MANIFEST) i = mcp_module.inspect_project(SIMPLE_MANIFEST) assert v["status"] == i["status"] assert v["project"] == i["project"] # --------------------------------------------------------------------------- # build (FR-1006) # --------------------------------------------------------------------------- def test_build_returns_docx_base64() -> None: result = mcp_module.build( SIMPLE_MANIFEST, [{"name": "doc.md", "content": SIMPLE_MARKDOWN}], ) assert result["status"] == "ok" docx_bytes = base64.b64decode(result["docx_base64"]) assert docx_bytes[:2] == b"PK" # ZIP/DOCX magic def test_build_returns_family_and_level() -> None: result = mcp_module.build( SIMPLE_MANIFEST, [{"name": "doc.md", "content": SIMPLE_MARKDOWN}], ) assert result["family"] == "article" assert result["feature_level"] == "level1" def test_build_invalid_manifest_error() -> None: result = mcp_module.build("project:\n name: x\n", []) assert result["status"] == "error" # --------------------------------------------------------------------------- # import_docx (FR-1007) # --------------------------------------------------------------------------- def _build_docx_b64() -> str: result = mcp_module.build( SIMPLE_MANIFEST, [{"name": "doc.md", "content": SIMPLE_MARKDOWN}], ) return result["docx_base64"] def test_import_docx_returns_files() -> None: docx_b64 = _build_docx_b64() result = mcp_module.import_docx(SIMPLE_MANIFEST, docx_b64) assert result["status"] == "ok" assert isinstance(result["files"], dict) assert result["mapping_status"] in ("redistributed", "merged") def test_import_bad_docx_error() -> None: bad_b64 = base64.b64encode(b"not a docx").decode() result = mcp_module.import_docx(SIMPLE_MANIFEST, bad_b64) assert result["status"] == "error" # --------------------------------------------------------------------------- # compare (FR-1008) # --------------------------------------------------------------------------- def test_compare_returns_drift_report() -> None: docx_b64 = _build_docx_b64() result = mcp_module.compare( SIMPLE_MANIFEST, docx_b64, [{"name": "doc.md", "content": SIMPLE_MARKDOWN}], ) assert result["status"] == "ok" assert "has_drift" in result assert "preserved" in result assert "degraded" in result assert "broken" in result # --------------------------------------------------------------------------- # run_tests (FR-1009) # --------------------------------------------------------------------------- def test_run_tests_invokes_roundtrip() -> None: result = mcp_module.run_tests( SIMPLE_MANIFEST, [{"name": "doc.md", "content": SIMPLE_MARKDOWN}], ) assert result["status"] in ("ok", "error") assert "run_id" in result # --------------------------------------------------------------------------- # invoke_workflow (FR-1012) # --------------------------------------------------------------------------- def test_invoke_workflow_single_file_roundtrip() -> None: result = mcp_module.invoke_workflow( "single-file-roundtrip", SIMPLE_MANIFEST, [{"name": "doc.md", "content": SIMPLE_MARKDOWN}], ) assert result["status"] in ("ok", "error") assert "run_id" in result assert "classification" in result assert "steps" in result def test_invoke_workflow_unknown_name() -> None: result = mcp_module.invoke_workflow("no-such", SIMPLE_MANIFEST, []) assert result["status"] == "error" assert result["errors"] # --------------------------------------------------------------------------- # get_evidence (FR-1013) # --------------------------------------------------------------------------- def test_get_evidence_not_found() -> None: result = mcp_module.get_evidence("no-such-run-id") assert result["status"] == "not_found" # --------------------------------------------------------------------------- # MCP server object exists and has the right name (FR-1001) # --------------------------------------------------------------------------- def test_mcp_object_exists() -> None: assert mcp_module.mcp is not None def test_mcp_name() -> None: assert mcp_module.mcp.name == "markidocx"