Initial curated ITWorx_MCP_Hub source from 368fba691ea8d23403b4d56b53b5ec670d7c5020
This commit is contained in:
commit
cb5be898ea
663 files changed
+82674
No files matched your search
@@ -0,0 +1,65 @@
|
||||
"""Compare a captured ProjectBrain tools/list with the reviewed Hub catalog.
|
||||
|
||||
Read-only: this never imports tools or edits catalog policy. Capture discovery
|
||||
from the owned connector and pass the JSON document using --discovery-file.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
|
||||
|
||||
def audit(discovery: dict[str, Any], catalog_root: Path) -> dict[str, Any]:
|
||||
tools = discovery.get("result", discovery).get("tools")
|
||||
if not isinstance(tools, list) or not tools:
|
||||
raise ValueError("non-empty tools/list result required")
|
||||
catalog = {}
|
||||
for path in sorted((catalog_root / "tools").glob("projectbrain-*.yaml")):
|
||||
spec = json.loads(path.read_text(encoding="utf-8"))["spec"]
|
||||
catalog[spec["canonicalName"]] = spec["inputSchema"]
|
||||
issues = []
|
||||
seen = set()
|
||||
for tool in tools:
|
||||
name = tool["name"]
|
||||
if name in seen:
|
||||
issues.append({"tool": name, "code": "duplicate_tool"})
|
||||
seen.add(name)
|
||||
if name not in catalog:
|
||||
issues.append({"tool": name, "code": "unreviewed_tool"})
|
||||
continue
|
||||
upstream = tool["inputSchema"]
|
||||
local = catalog[name]
|
||||
for field in sorted(set(upstream.get("properties", {})) - set(local.get("properties", {}))):
|
||||
issues.append({"tool": name, "code": "missing_field", "field": field})
|
||||
if set(upstream.get("required", [])) != set(local.get("required", [])):
|
||||
issues.append({"tool": name, "code": "required_fields_differ"})
|
||||
for field, value in upstream.get("properties", {}).items():
|
||||
target = local.get("properties", {}).get(field, {})
|
||||
if "type" in value and "type" in target and value["type"] != target["type"]:
|
||||
issues.append({"tool": name, "code": "field_type_differs", "field": field})
|
||||
if "enum" in value and "enum" in target and value["enum"] != target["enum"]:
|
||||
issues.append({"tool": name, "code": "field_enum_differs", "field": field})
|
||||
for name in sorted(set(catalog) - seen):
|
||||
issues.append({"tool": name, "code": "upstream_tool_missing"})
|
||||
return {"passed": not issues, "toolCount": len(tools), "issues": issues}
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--discovery-file", type=Path, required=True)
|
||||
parser.add_argument("--catalog-root", type=Path, default=ROOT / "catalog")
|
||||
args = parser.parse_args()
|
||||
if args.discovery_file.stat().st_size > 2 * 1024 * 1024:
|
||||
parser.error("discovery exceeds 2 MiB")
|
||||
result = audit(json.loads(args.discovery_file.read_text(encoding="utf-8")), args.catalog_root)
|
||||
print(json.dumps(result, sort_keys=True))
|
||||
return 0 if result["passed"] else 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in new issue
Block a user