1"""Opaque MCP acceptance (A5): a mock MCP server exposes only its tool contract. AKOS records the declared contract and the2visible invocations, flags opaque_internal_implementation=true, opens critical knowledge debt, and the verified research3export is BLOCKED — an independently documented API (Open-Meteo AKP) is a tested alternative, not proof of the MCP internals.45 AKOS_URL=… AKOS_TOKEN=… python demo_opaque.py [--project research-demo]6"""7from __future__ import annotations8import argparse9import json10import os11import sys12sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", ".."))13from akos.sdk import Akos, AkosError # noqa: E4021415ap = argparse.ArgumentParser(); ap.add_argument("--project", default="research-demo"); a = ap.parse_args()16A = Akos()17MOCK = {"server": "mock-weather-mcp", "version": "1.0", "description": "Mock MCP server: returns a current temperature for a city. Its HTTP calls (if any) are hidden.",18 "tools": [{"name": "get_weather", "description": "Current temperature for a city", "inputSchema": {"type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"]},19 "outputSchema": {"type": "object", "properties": {"city": {"type": "string"}, "temperature_c": {"type": "number"}, "observed_at": {"type": "string"}}}}],20 "invocations": [{"tool": "get_weather", "input": {"city": "Montreal"}, "output": {"city": "Montreal", "temperature_c": 4.2, "observed_at": "2026-11-01T12:00:00Z"}},21 {"tool": "get_weather", "input": {"city": "Quebec"}, "output": {"city": "Quebec", "temperature_c": 1.9, "observed_at": "2026-11-01T12:00:00Z"}}]}22print("### register opaque MCP server (declared contract + visible invocations only)")23j = A.discover(project_id=a.project, kind="mcp", name="Mock weather MCP", provider_slug="mock-weather-mcp", provider_name="Mock weather MCP server", mcp_contract=MOCK)24res = A.wait_job(j["job_id"])25if res["state"] != "done":26 print("FAILED", res.get("error")); sys.exit(1)27r = res["result"]; print(json.dumps(r, indent=1))28api = A.api(r["api_id"]); pkg = A.package(r["package_id"])29print("api kind:", api["kind"], "opaque_internal_implementation:", api["opaque_internal_implementation"], "lifecycle:", api["lifecycle"], "knowledge_state:", api["knowledge_state"])30print("debt:", [(d["kind"], d["severity"], d["status"]) for d in api["debt"]])31print("package lifecycle:", pkg["lifecycle"], "manifest.opaque:", pkg["manifest"]["opaque_internal_implementation"], "mcp-tools.json note:", json.loads(A.client_source(pkg["id"], "mcp-tools.json"))["note"][:80])32exs = [e for e in A.executions(project_id=a.project, limit=50) if e["api_name"] == "Mock weather MCP"]33print("visible invocations recorded:", len(exs), "observed flags:", sorted({e["observed"] for e in exs}), "states:", sorted({e["state"] for e in exs}))34print("\n### dataset from the MCP outputs, then verified export")35ds = A.create_dataset(project_id=a.project, name="Mock MCP weather outputs", execution_ids=[e["id"] for e in exs], identifiers=["city"], units={"temperature_c": "degC"}, granularity="city-instant")36failed = [c for c in ds["assessment"]["checks"] if not c["ok"]]37print("dataset:", ds["id"], ds["row_count"], "rows →", ds["verification"]); [print(" ✗", c["check"], "—", c["detail"]) for c in failed]38jr = A.export(ds["id"], verified=True); out = A.wait_job(jr["job_id"])["result"]39print("verified export:", "BLOCKED" if out.get("blocked") else out.get("verification_label"), "|", "; ".join(out.get("reasons", []))[:300])40assert out.get("blocked"), "verified export must be blocked for opaque sources"41jr = A.export(ds["id"], verified=False); out2 = A.wait_job(jr["job_id"])["result"]42print("unverified export:", out2.get("verification_label"), out2.get("bytes"), "bytes (clearly labelled, limitations listed in manifest.reproducibility.limitations)")43alt = A.package("open-meteo.open-meteo-forecast")44print(f"\nindependent alternative: {alt['akp_id']} v{alt['version']} lifecycle={alt['lifecycle']} — documented API with tested client; it does NOT prove what the MCP server does internally.")45json.dump({"api_id": r["api_id"], "package_id": r["package_id"], "dataset_id": ds["id"], "blocked_reasons": out.get("reasons")}, open("/tmp/akos-opaque-ids.json", "w"), indent=1)46