#!/usr/bin/env python3 """Validate MCP baseline documents for P19+MCP-1.""" from __future__ import annotations import json import sys from pathlib import Path ROOT = Path(__file__).resolve().parent.parent DOC_PATH = ROOT / "docs" / "mcp-tools.md" EXAMPLE_PATH = ROOT / ".mcp.json.example" AGENTS_PATH = ROOT / "AGENTS.md" def fail(message: str) -> int: print(f"[ERR] {message}") return 1 def require(text: str, needle: str, label: str, errors: list[str]) -> None: if needle not in text: errors.append(f"missing {label}: {needle}") def main() -> int: errors: list[str] = [] if not DOC_PATH.exists(): errors.append(f"missing file: {DOC_PATH}") if not EXAMPLE_PATH.exists(): errors.append(f"missing file: {EXAMPLE_PATH}") if not AGENTS_PATH.exists(): errors.append(f"missing file: {AGENTS_PATH}") if errors: for error in errors: print(f"[ERR] {error}") return 1 doc_text = DOC_PATH.read_text(encoding="utf-8") agents_text = AGENTS_PATH.read_text(encoding="utf-8") require(doc_text, "## Enabled Servers", "section", errors) require(doc_text, "- `postgres`", "enabled postgres", errors) require(doc_text, "## Candidate Servers (Not Enabled)", "section", errors) require(doc_text, "`github`", "candidate github", errors) require(doc_text, "postgres:query", "tool", errors) require(doc_text, "READ ONLY", "readonly phrase", errors) require(doc_text, "不提交真实密钥/连接串", "secret hygiene", errors) require(doc_text, "github deferred", "github deferred", errors) if "docs/mcp-tools.md" not in agents_text: errors.append("AGENTS.md missing docs/mcp-tools.md reference") try: example = json.loads(EXAMPLE_PATH.read_text(encoding="utf-8")) except json.JSONDecodeError as exc: errors.append(f"invalid json in .mcp.json.example: {exc}") example = {} servers = example.get("mcpServers") if isinstance(example, dict) else None if not isinstance(servers, dict): errors.append(".mcp.json.example missing mcpServers object") else: if set(servers.keys()) != {"postgres"}: errors.append(f".mcp.json.example must contain only postgres server, got: {sorted(servers.keys())}") postgres = servers.get("postgres") if not isinstance(postgres, dict): errors.append("postgres server config missing or invalid") else: command = postgres.get("command") args = postgres.get("args") if command != "npx": errors.append(f"postgres command must be npx, got: {command}") if not isinstance(args, list): errors.append("postgres args must be a list") else: flattened = " ".join(str(item) for item in args) if "@modelcontextprotocol/server-postgres" not in flattened: errors.append("postgres args missing official server package") if "" not in flattened: errors.append("postgres args missing readonly user placeholder") if "" not in flattened or "" not in flattened or "" not in flattened or "" not in flattened: errors.append("postgres args missing connection placeholders") example_text_upper = EXAMPLE_PATH.read_text(encoding="utf-8").upper() for forbidden in ["GITHUB", "TOKEN"]: if forbidden in example_text_upper: errors.append(f".mcp.json.example contains forbidden token: {forbidden}") if "postgresql://localhost/" in EXAMPLE_PATH.read_text(encoding="utf-8"): errors.append(".mcp.json.example must not contain a concrete localhost connection string") if errors: print("[ERR] MCP tools validation failed") for error in errors: print(f" - {error}") return 1 print("[OK] MCP tools baseline validated (docs/mcp-tools.md, .mcp.json.example, AGENTS.md)") return 0 if __name__ == "__main__": raise SystemExit(main())