"""Documentation checks for external Jenkins/GlitchTip MCP registration (#151/#152).""" from pathlib import Path REPO_ROOT = Path(__file__).resolve().parent.parent DOC = REPO_ROOT / "docs" / "mcp-client-registration.md" def _doc_text(): assert DOC.is_file(), "missing docs/mcp-client-registration.md" return DOC.read_text(encoding="utf-8") def test_registration_doc_names_canonical_servers(): text = _doc_text() assert "jenkins-mcp" in text assert "glitchtip-mcp" in text assert "Historical names" in text assert "jenkins-readonly" in text assert "glitchtip-readonly" in text def test_registration_doc_lists_expected_tool_visibility(): text = _doc_text() for tool in ( "jenkins_whoami", "jenkins_list_jobs", "jenkins_latest_build", "jenkins_build_status", "jenkins_get_build", "glitchtip_whoami", "glitchtip_list_projects", "glitchtip_list_unresolved", "glitchtip_get_issue", "glitchtip_recent_events", "glitchtip_search", ): assert tool in text def test_registration_doc_requires_reload_and_negative_case(): text = _doc_text() lower = text.lower() assert "reconnect" in lower assert "reload" in lower assert "enabled but no usable tools" in lower assert "SKIPPED" in text def test_registration_doc_preserves_boundaries(): text = " ".join(_doc_text().split()) for phrase in ( "Do not add Jenkins or GlitchTip credentials to the Gitea MCP server", "do not add Gitea write credentials to the GlitchTip server", "must not expose build trigger tools", "jenkins-write-mcp", "jenkins_mcp.write_server", "remains read-only", ): assert phrase in text def test_registration_doc_pins_glitchtip_filing_boundary(): text = " ".join(_doc_text().split()) for phrase in ( "GlitchTip-to-Gitea filing is a separate library-only orchestrator in " "`mcp-control-plane`", "real GlitchTip read path", "dedup before any Gitea create action", "create/link/skip decisions", "fail closed on mutation-audit failure before any Gitea create, link, " "or comment mutation", "must use a separate write-boundary server/profile", "must not be exposed by `glitchtip-mcp`", ): assert phrase in text def test_registration_doc_separates_jenkins_trigger_from_read_surface(): text = _doc_text() assert "jenkins_trigger_build" in text assert "must **not** appear on `jenkins-mcp`" in text assert "not" in text.lower() and "registered by default" in text.lower() def test_registration_doc_has_no_secret_material_or_live_urls(): text = _doc_text() for marker in ( "https://", "http://", "Authorization:", "BEGIN PRIVATE KEY", "ghp_", "token-value", ): assert marker not in text def test_related_docs_link_registration_doc(): for name in ( "README.md", "docs/llm-workflow-runbooks.md", "docs/architecture/jenkins-readonly-build-status-design.md", "docs/architecture/glitchtip-readonly-tools-design.md", ): text = (REPO_ROOT / name).read_text(encoding="utf-8") assert "mcp-client-registration.md" in text, ( f"{name} does not link docs/mcp-client-registration.md") def test_related_docs_keep_jenkins_trigger_off_read_surface(): for name in ( "docs/safety-model.md", "docs/architecture/jenkins-readonly-build-status-design.md", ): text = (REPO_ROOT / name).read_text(encoding="utf-8") assert "jenkins-write-mcp" in text assert "jenkins_mcp.write_server" in text assert "jenkins-mcp" in text def test_glitchtip_filing_contract_doc_covers_issue_153_acceptance(): text = ( REPO_ROOT / "docs" / "architecture" / "glitchtip-to-gitea-workflow-design.md" ).read_text(encoding="utf-8") flattened = " ".join(text.split()) for phrase in ( "**Status:** Contract for the library-only implementation in " "`Scaled-Tech-Consulting/mcp-control-plane` (#57)", "**Issue:** #153", "not exposed through `glitchtip-mcp`", "real GlitchTip read path", "must not use mocked GlitchTip issue data", "separate write-boundary server/profile", "fail-closed mutation audit before create/link/comment actions", "Deduplication before create", "Create, link, and skip decisions must be represented in tests", "Mutation audit fails closed", ): assert phrase in flattened