szl-holdings/hatun-mcp

Hatun-MCP — doctrine-aware Model Context Protocol server. 16 SZL tools under PURIQ governance (Yuyay-13 gate, Khipu receipts, DSSE-signed). Streamable HTTP + SSE.

1

stars

128

commits

Python

primary language

Sep 8, 2026

updated

a-11-oy.com
agentic
agentic-ai
ai
airgap
defense-tech
doctrine-v11
governance
governed-ai
mcp
model-context-protocol
szl-holdings
Browse cluster: Policy-as-Code and Kubernetes Governance

README


title: Hatun MCP — Governed Agent Gateway emoji: 🪢 colorFrom: indigo colorTo: blue sdk: docker app_port: 7860 pinned: false license: apache-2.0 short_description: Source-bound MCP gateway with signed governance receipts

License Doctrine v11 LOCKED CI SLSA

🪢 hatun-mcp

The great context protocolhatun (Quechua) = "big / great".

The one signed MCP endpoint that aggregates the SZL backend services — the a11oy command platform (and its live immune, companion and llm-router organs) plus killinchu (drones & vessels) — under PURIQ governance and re-exposes their tools to any MCP client.

Hatun Gateway · GitHub Org · LLM Router

Canonical runtime source. This repository owns the Python gateway, governed tool catalog, Streamable HTTP transport, and container contract. The standalone Hatun Hugging Face publisher was retired on September 3, 2026; hf-deploy must not be recreated. The public product experience is Hatun Gateway, which is not itself proof that this package's /mcp/ endpoint or a newly added tool is deployed. See the surface contract. The monorepo copy at platform/packages/hatun-mcp is a non-canonical embedded copy (it carries CANONICAL.md pointing here) that exposes a smaller tool set for local imports and must not diverge from this server's contracts. Folding the platform copy in is a later founder step; repos are not deleted here. Λ = Conjecture 1 (advisory) is preserved verbatim.

receipts.in ≡ receipts.out


What this is

A real, operational Model Context Protocol server built on the official mcp Python SDK (mcp.server.fastmcp.FastMCP). Every tool call is governed by the PURIQ formula:

  1. Authenticate the client (SZL API key → client_id); anonymous calls are declined.
  2. Yuyay-13 gate on the input (input-as-data; OWASP MCP06 injection defense).
  3. Reputation factor Hatun_MCP(client) ∈ [0,1].
  4. 2-person Yuyay gate for state-changing tools (e.g. killinchu_cue, halt_drone).
  5. Call the real organ backend within a latency budget.
  6. Mint a Khipu receipt on success and failure (append-only sha256 DAG).
  7. Return a DSSE-signed response — the client receives the receipt hash.

Choose your route

AudienceStart hereEvidence boundary
DeveloperRun locally, then inspect tools/listLocal startup proves only the local process; backend reachability is separate
IntegratorMCP client setupThe checked-in client configuration is SAMPLE and does not include credentials
EvaluatorHosted health contracts, then Tests/healthz is liveness; /readyz is signed-release readiness; neither is an uptime guarantee

KANCHAY status contract

  • LIVE: a runtime-backed route with source and observation time. It never means perpetual availability.
  • PARTIAL: Hatun is locally ready, but one or more required upstream organ observations are missing, stale, or degraded.
  • SAMPLE: checked-in configuration, payload, or transcript for reuse; not observed runtime evidence.
  • SIMULATED: a mocked backend or hermetic test fixture. CI intentionally uses these where external services would make tests nondeterministic.
  • UNAVAILABLE: the dependency or readiness check cannot produce a usable result. Preserve the reason and do not substitute sample data.

Tools exposed

  • 26 static tools registered at import (verifiable: tools/list returns 26 with HATUN_MCP_DISABLE_DYNAMIC=true):
    • 20 szl_* toolsszl_a11oy_code_chat, szl_a11oy_operator_reason, szl_a11oy_sentinel_scan, szl_anatomy_3d_render, szl_doctrine_lookup, szl_drone_lookup, szl_formula_evaluate, szl_github_estate_snapshot, szl_khipu_verify, szl_killinchu_cue, szl_killinchu_detect, szl_lean_verify, szl_puriq_evaluate, szl_companion_reason, szl_immune_scan, szl_thesis_query, szl_wayra_recent, szl_yachay_dome_predict, szl_yuyay_score, and szl_lambda_quorum (Byzantine Λ verdict).

      Two tools were renamed 2026-06-16 to honest organ names — szl_immune_scan (was the retired codename scan tool) and szl_companion_reason (was the retired codename reason tool). See DEPRECATED.md for the old→new mapping. The old names are not served (they are not registered in tools/list).

    • 6 governance toolsyuyay_gate_check, khipu_append_and_verify, dsse_sign, mesh_quorum_status, puriq_master_tool, governance_pacbayes_bound.
  • Service-derived tools registered dynamically at startup from each backend service's live catalog at /api/<service>/v1/mcp/tools, named <service>_<tool>. The dynamic count is probe-dependent: it equals 26 + (whatever the reachable services publish), and is 0 extra when dynamic registration is disabled or all services are unreachable.

Public GitHub estate evidence

Call szl_github_estate_snapshot with {} to observe the fixed public szl-holdings organization. This is a structural inventory tool, not an LLM answer or a merge bot. It accepts no organization, URL, token, cursor, or other argument. GitHub access uses tokenless, redirect-disabled GETs to a fixed origin; environment credentials and proxies are not inherited by that client.

The observer reports repository identities and default-branch names, bounded open-PR base/head SHAs, draft state, and check runs queried at those exact head SHAs. Citations include request paths and parameters, response byte lengths and SHA-256 digests. A canonical snapshot digest is included in the Khipu receipt and its DSSE payload; a configured P-256 key signs that receipt. Without a key, the envelope remains explicitly PLACEHOLDER with no signatures. A digest or a complete inventory is not an independent witness or a cryptographic signature.

Hard per-call limits: 15 seconds, 20 requests, 3 repository pages (300 records), 50 open PR search results, 100 check runs per PR, 1 MiB of accepted response-body data per response and 4 MiB accepted across the call. Exhaustion stops queued requests and further body acceptance. These are application acceptance limits, not a measurement of wire traffic or transport prefetch; already-delivered but rejected bytes are not counted as accepted. Overflow, timeouts, rate limits, malformed records, stale PR search evidence, and absent or unrecognized check results produce explicit gaps and INCOMPLETE or UNAVAILABLE. Zero checks are UNKNOWN, never success. COMPLETE means the declared observation scope was covered; failed CI may still be completely observed. It does not mean the estate is operational or safe to merge.

This v1 deliberately does not attest private repositories, resolved default branch heads, legacy commit-status contexts, reviews, protection rules, merge eligibility, HF publication, model quality/training, or deployed runtime health. Its multiple requests are not an atomic provider snapshot. Each response is input data, not instructions. Normal Hatun authentication and receipt handling still apply, including optional operator-configured SZL_RECEIPT_SINK forwarding; the GitHub observer performs no provider mutations.

Naming note. The three previously-codenamed backends were purged; their capabilities are now served directly by the live honest a11oy organs on a-11-oy.com: the immune organ (egress policy/gates inspector — Hukulla), the companion organ (operator / reasoning console), and the llm organ (open-LLM tier router). Hatun-MCP addresses them by these honest role names; the live routes are published in /openapi.json.

Recorded reachability snapshot (HONESTY OVER CHECKLIST)

The table below records repository evidence dated 2026-06-16. It is not a current health probe. /healthz and /readyz establish Hatun's local process, receipt chain, and signer only; they do not probe the upstream organs. Before presenting any row as currently LIVE, make a separate bounded, read-only probe of that row's listed route (or a documented non-mutating readiness route), and record the response status, source, and observation timestamp. For POST-only or state-changing surfaces, use a pre-authorized non-mutating contract probe or a timestamped receipt; never trigger an action merely to claim availability. If any required upstream observation is missing, stale, or unusable, present that row as PARTIAL or UNAVAILABLE.

Backend organCatalog routeRecorded state (2026-06-16)
a11oy — llm open-LLM tier routerGET /api/a11oy/v1/llm/tiersLIVE (200)llm_tiers derived from the live tier catalog
killinchu/api/killinchu/v1/mcp/toolsLIVE — 4 tools (cue/halt_drone are 2-person)
a11oy — companion operator / reasoning console/api/a11oy/v1/companion/{ask,act,recommend}LIVE (200) — 3 tools derived from live action routes (no JSON /v1/mcp/tools catalog)
a11oy — immune (Hukulla) egress policy inspectorGET /api/a11oy/v1/immune/gatesLIVE (200, gates-derived) — gates + screen/verdict; the immune screen is the signed /immune/verdict route (there is no separate /screen)
a11oy — command / flagship/api/a11oy/v1/mcp/toolsRegisters a11oy-flagship tools when the JSON catalog is exposed, else one honest a11oy_status tool. Self-heals on the next server restart once the catalog returns 200 — no code change, no fabricated stubs.

Purge note (2026-06-16). The three previously-codenamed backends were purged (their old routes now 404). Hatun-MCP was repointed to the live honest a11oy twins above and verified 200 before wiring. No tool is ever pointed at a 404; where a sub-route does not exist (e.g. /immune/screen) the tool maps to the closest real route (/immune/verdict) and the mapping is disclosed in the adapter docstring and the catalog reason.

Byzantine quorum + BLS aggregate

szl_lambda_quorum fans a governance-critical Λ verdict out to the five backend services and decides under a Byzantine n ≥ 3f+1 quorum (n=5, f=1): ≥ 4 services must be reachable and ≥ 3 must agree. Participating receipts are BLS12-381 aggregated (py_ecc; honest sha256 Merkle-root fallback if the BLS backend is absent). If any organ's policy route is not live, quorum degrades gracefully (n=4 still satisfies n ≥ 3f+1) and discloses the degradation in governance.quorum.


Run locally (stdio)

pip install -r requirements.txt
python -m hatun_mcp.server          # stdio mode for Claude Desktop / Codex

Run hosted (Streamable HTTP)

uvicorn hatun_mcp.server_http:app --host 0.0.0.0 --port 7860
# MCP endpoint:  http://127.0.0.1:7860/mcp   (legacy SSE at /sse)
# Process liveness: http://127.0.0.1:7860/healthz
# Signed-release readiness: http://127.0.0.1:7860/readyz

The DSSE signing key is injected at runtime via the HATUN_MCP_SIGNING_KEY (PEM) operator-managed secret; without it the signer runs in honest PLACEHOLDER mode (clearly labeled, never a fake signature).

/healthz proves that the process and local receipt chain can answer. /readyz is the fail-closed investor/deployment contract: it returns 200 only when the receipt chain verifies and a non-placeholder signing key is active; otherwise it returns 503 with the failing check named. The public server card advertises only the API-key scheme that this server actually implements.

MCP manifest attestation

GET /.well-known/mcp-manifest-attestation returns a cached integrity binding for the exact raw bytes served by GET /.well-known/mcp (all server-card aliases serve those same bytes). It contains a deterministic https://in-toto.io/Statement/v1 with SHA-256 subject digest and the custom predicate type https://szlholdings.com/attestations/mcp-manifest/v1. When the existing P-256 signing key is configured, the statement is carried in a real DSSE envelope whose payloadType is application/vnd.in-toto+json. Without that key, the response is explicitly signing.state=UNSIGNED with dsseEnvelope=null; an empty signature is never presented as signed.

The artifact is built once at process start and accepts no caller-supplied signing payload. It does not mint a Khipu receipt. Its scope is byte integrity only: it does not attest runtime tool parity, upstream availability, or the behavior behind the card. The MCP server card and this well-known route are an SZL DRAFT extension, not a claim of a ratified MCP discovery standard. keyid is only a hint; verifiers must establish trust in the P-256 public key out of band (the same-origin /pubkey route is not an independent trust anchor). Transparency-log inclusion remains explicitly unavailable.

Evaluate the hosted contract

curl -i http://127.0.0.1:7860/healthz
curl -i http://127.0.0.1:7860/readyz
curl -s http://127.0.0.1:7860/api/console-state

/api/console-state (hatun_mcp/state.py) is the read behind the human console at /. The commands above target your locally started server. For a deployment, use its admitted operator-provided origin, not the retired standalone Space host. It is assembled in-request from this process only: the tool catalogue is enumerated from the LIVE FastMCP registry (not a hand-maintained list), the receipt depth and head hash come from the live Khipu chain, and card_parity reports a MEASURED comparison between the published server card and that runtime registry. Anything it cannot read is returned with an honest label (UNAVAILABLE) and no number — there is no seeded snapshot, so the console shows UNAVAILABLE rather than a stale value when a reading fails. It mints no receipt and attests nothing beyond the reading itself.

Record the response status and observation time. Report healthz=200 as Hatun process liveness only. Report readyz=200 as Hatun's repository-defined local receipt-chain and signer readiness only. These checks do not establish killinchu or a11oy organ availability. Before labeling any upstream row LIVE, separately run a bounded, read-only probe of its listed route (or a documented non-mutating readiness route) and record the route, response status, source, and observation timestamp. For POST-only or state-changing surfaces, require a pre-authorized non-mutating contract probe or timestamped receipt instead of triggering an action. If Hatun is ready but an upstream observation is missing, stale, or unusable, report that row as PARTIAL or UNAVAILABLE. Never fall back to the sample client configuration.


MCP client setup

Claude Desktop

The snippets below are SAMPLE local-server configurations. Start the HTTP server first, configure an accepted API key, and replace szl_YOUR_KEY. For a remote deployment, substitute the admitted operator-provided HTTPS MCP URL. Drop examples/claude-desktop-config.json into ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) / %APPDATA%\Claude\claude_desktop_config.json (Windows), replacing szl_YOUR_KEY:

{
  "mcpServers": {
    "hatun-mcp": {
      "command": "npx",
      "args": ["-y", "mcp-remote",
        "http://127.0.0.1:7860/mcp/",
        "--header", "Authorization: Bearer szl_YOUR_KEY"]
    }
  }
}

Codex (~/.codex/config.toml)

[mcp_servers.hatun-mcp]
command = "npx"
args = ["-y", "mcp-remote", "http://127.0.0.1:7860/mcp/",
        "--header", "Authorization: Bearer szl_YOUR_KEY"]

Continue (~/.continue/config.json)

{
  "experimental": {
    "modelContextProtocolServers": [
      {
        "transport": {
          "type": "stdio",
          "command": "npx",
          "args": ["-y", "mcp-remote",
            "http://127.0.0.1:7860/mcp/",
            "--header", "Authorization: Bearer szl_YOUR_KEY"]
        }
      }
    ]
  }
}

Tests

HATUN_MCP_DISABLE_DYNAMIC=true python -m pytest tests/ -q
# tests/test_server.py    — list tools, call a tool, assert response shape
# tests/test_github_estate_snapshot.py — bounded public GitHub observer, mocked provider
# tests/test_quorum.py    — quorum math + threshold edge cases + BLS aggregate
# tests/test_adapters.py  — mocked organ endpoints, adapter wiring + honest gaps
# tests/test_governance.py— Khipu chain, Yuyay gate, PURIQ factor (pre-existing)
# tests/test_http_routes.py — exact-byte card attestation + public HTTP contracts

The server tests also import the estate regression class so the existing explicit-file hosted CI gate exercises it. They verify real in-memory MCP discovery/calls, argument rejection, canonical digest binding, and an ephemeral P-256 signature. Provider responses in these tests are SIMULATED; passing them does not publish the new tool or establish current GitHub/HF health.

python tests/proof_inmemory.py exercises the real in-memory MCP protocol and checks exact static runtime/server-card name parity. The proof disables dynamic catalog probing and receipt-sink forwarding in its own process. CI also runs it from an unrelated working directory to verify the documented direct command.

The Ouroboros loop (doctrine cross-reference)

hatun-mcp does not implement the estate's Ouroboros bounded-recursion kernel itself; its PURIQ orchestrator is a bounded, single-pass per-tool-call flow, not recursion. This section is a doctrine cross-reference plus an honest note on how that flow embodies the loop's receipt-closed identity (receipts.in ≡ receipts.out, already carried in this README).

The canonical definition is the receipt-closed kernel szl-holdings/ouroborossrc/loop-kernel.ts (runLoop): bounded recursion with measurable convergence that MUST terminate on one of four exit conditions — converged | consistent | aborted | budgetExhausted — and emits a governance receipt for every run. The trace is the product.

How hatun-mcp embodies that primitive (in hatun_mcp/puriq.py):

  • Bounded & terminating. Each tool call is a finite pipeline — Yuyay-13 gate → mesh quorum (Byzantine n ≥ 3f+1) → HUKLLA tripwire → Khipu append → DSSE-sign → compose the master-formula scalar — that always terminates within a latency budget and returns a receipt hash. There is no unbounded loop.
  • Receipt-closed. Every call mints a Khipu link on an append-only sha256 DAG and the client receives the receipt hash. That is this repo's live realization of the header identity receipts.in ≡ receipts.out — a metaphor (doctrine, not math), where each signed receipt is fed back into the DAG as an auditable input.

Honesty (Doctrine v11 · 749/14/163): Λ is consumed here as an input scalar in [0,1] and is Conjecture 1 — advisory, never a proven theorem. This is a bounded, terminating governance flow — it makes no perpetual-motion or zero-cost claim.


Doctrine v11 LOCKED — 749 / 14 / 163 · Λ = Conjecture 1 (NOT a theorem) · SLSA L1 honest · L2 verified-provenance on roadmap (L3 not claimed) receipts.in ≡ receipts.out

Signed-off-by: Yachay <yachay@szlholdings.ai> Co-Authored-By: Perplexity Computer Agent <agent@perplexity.ai>

Contributors

szl-holdings/hatun-mcp

Hatun-MCP — doctrine-aware Model Context Protocol server. 16 SZL tools under PURIQ governance (Yuyay-13 gate, Khipu receipts, DSSE-signed). Streamable HTTP + SSE.

1

stars

128

commits

Python

primary language

Sep 8, 2026

updated

a-11-oy.com
agentic
agentic-ai
ai
airgap
defense-tech
doctrine-v11
governance
governed-ai
mcp
model-context-protocol
szl-holdings
Browse cluster: Policy-as-Code and Kubernetes Governance

README


title: Hatun MCP — Governed Agent Gateway emoji: 🪢 colorFrom: indigo colorTo: blue sdk: docker app_port: 7860 pinned: false license: apache-2.0 short_description: Source-bound MCP gateway with signed governance receipts

License Doctrine v11 LOCKED CI SLSA

🪢 hatun-mcp

The great context protocolhatun (Quechua) = "big / great".

The one signed MCP endpoint that aggregates the SZL backend services — the a11oy command platform (and its live immune, companion and llm-router organs) plus killinchu (drones & vessels) — under PURIQ governance and re-exposes their tools to any MCP client.

Hatun Gateway · GitHub Org · LLM Router

Canonical runtime source. This repository owns the Python gateway, governed tool catalog, Streamable HTTP transport, and container contract. The standalone Hatun Hugging Face publisher was retired on September 3, 2026; hf-deploy must not be recreated. The public product experience is Hatun Gateway, which is not itself proof that this package's /mcp/ endpoint or a newly added tool is deployed. See the surface contract. The monorepo copy at platform/packages/hatun-mcp is a non-canonical embedded copy (it carries CANONICAL.md pointing here) that exposes a smaller tool set for local imports and must not diverge from this server's contracts. Folding the platform copy in is a later founder step; repos are not deleted here. Λ = Conjecture 1 (advisory) is preserved verbatim.

receipts.in ≡ receipts.out


What this is

A real, operational Model Context Protocol server built on the official mcp Python SDK (mcp.server.fastmcp.FastMCP). Every tool call is governed by the PURIQ formula:

  1. Authenticate the client (SZL API key → client_id); anonymous calls are declined.
  2. Yuyay-13 gate on the input (input-as-data; OWASP MCP06 injection defense).
  3. Reputation factor Hatun_MCP(client) ∈ [0,1].
  4. 2-person Yuyay gate for state-changing tools (e.g. killinchu_cue, halt_drone).
  5. Call the real organ backend within a latency budget.
  6. Mint a Khipu receipt on success and failure (append-only sha256 DAG).
  7. Return a DSSE-signed response — the client receives the receipt hash.

Choose your route

AudienceStart hereEvidence boundary
DeveloperRun locally, then inspect tools/listLocal startup proves only the local process; backend reachability is separate
IntegratorMCP client setupThe checked-in client configuration is SAMPLE and does not include credentials
EvaluatorHosted health contracts, then Tests/healthz is liveness; /readyz is signed-release readiness; neither is an uptime guarantee

KANCHAY status contract

  • LIVE: a runtime-backed route with source and observation time. It never means perpetual availability.
  • PARTIAL: Hatun is locally ready, but one or more required upstream organ observations are missing, stale, or degraded.
  • SAMPLE: checked-in configuration, payload, or transcript for reuse; not observed runtime evidence.
  • SIMULATED: a mocked backend or hermetic test fixture. CI intentionally uses these where external services would make tests nondeterministic.
  • UNAVAILABLE: the dependency or readiness check cannot produce a usable result. Preserve the reason and do not substitute sample data.

Tools exposed

  • 26 static tools registered at import (verifiable: tools/list returns 26 with HATUN_MCP_DISABLE_DYNAMIC=true):
    • 20 szl_* toolsszl_a11oy_code_chat, szl_a11oy_operator_reason, szl_a11oy_sentinel_scan, szl_anatomy_3d_render, szl_doctrine_lookup, szl_drone_lookup, szl_formula_evaluate, szl_github_estate_snapshot, szl_khipu_verify, szl_killinchu_cue, szl_killinchu_detect, szl_lean_verify, szl_puriq_evaluate, szl_companion_reason, szl_immune_scan, szl_thesis_query, szl_wayra_recent, szl_yachay_dome_predict, szl_yuyay_score, and szl_lambda_quorum (Byzantine Λ verdict).

      Two tools were renamed 2026-06-16 to honest organ names — szl_immune_scan (was the retired codename scan tool) and szl_companion_reason (was the retired codename reason tool). See DEPRECATED.md for the old→new mapping. The old names are not served (they are not registered in tools/list).

    • 6 governance toolsyuyay_gate_check, khipu_append_and_verify, dsse_sign, mesh_quorum_status, puriq_master_tool, governance_pacbayes_bound.
  • Service-derived tools registered dynamically at startup from each backend service's live catalog at /api/<service>/v1/mcp/tools, named <service>_<tool>. The dynamic count is probe-dependent: it equals 26 + (whatever the reachable services publish), and is 0 extra when dynamic registration is disabled or all services are unreachable.

Public GitHub estate evidence

Call szl_github_estate_snapshot with {} to observe the fixed public szl-holdings organization. This is a structural inventory tool, not an LLM answer or a merge bot. It accepts no organization, URL, token, cursor, or other argument. GitHub access uses tokenless, redirect-disabled GETs to a fixed origin; environment credentials and proxies are not inherited by that client.

The observer reports repository identities and default-branch names, bounded open-PR base/head SHAs, draft state, and check runs queried at those exact head SHAs. Citations include request paths and parameters, response byte lengths and SHA-256 digests. A canonical snapshot digest is included in the Khipu receipt and its DSSE payload; a configured P-256 key signs that receipt. Without a key, the envelope remains explicitly PLACEHOLDER with no signatures. A digest or a complete inventory is not an independent witness or a cryptographic signature.

Hard per-call limits: 15 seconds, 20 requests, 3 repository pages (300 records), 50 open PR search results, 100 check runs per PR, 1 MiB of accepted response-body data per response and 4 MiB accepted across the call. Exhaustion stops queued requests and further body acceptance. These are application acceptance limits, not a measurement of wire traffic or transport prefetch; already-delivered but rejected bytes are not counted as accepted. Overflow, timeouts, rate limits, malformed records, stale PR search evidence, and absent or unrecognized check results produce explicit gaps and INCOMPLETE or UNAVAILABLE. Zero checks are UNKNOWN, never success. COMPLETE means the declared observation scope was covered; failed CI may still be completely observed. It does not mean the estate is operational or safe to merge.

This v1 deliberately does not attest private repositories, resolved default branch heads, legacy commit-status contexts, reviews, protection rules, merge eligibility, HF publication, model quality/training, or deployed runtime health. Its multiple requests are not an atomic provider snapshot. Each response is input data, not instructions. Normal Hatun authentication and receipt handling still apply, including optional operator-configured SZL_RECEIPT_SINK forwarding; the GitHub observer performs no provider mutations.

Naming note. The three previously-codenamed backends were purged; their capabilities are now served directly by the live honest a11oy organs on a-11-oy.com: the immune organ (egress policy/gates inspector — Hukulla), the companion organ (operator / reasoning console), and the llm organ (open-LLM tier router). Hatun-MCP addresses them by these honest role names; the live routes are published in /openapi.json.

Recorded reachability snapshot (HONESTY OVER CHECKLIST)

The table below records repository evidence dated 2026-06-16. It is not a current health probe. /healthz and /readyz establish Hatun's local process, receipt chain, and signer only; they do not probe the upstream organs. Before presenting any row as currently LIVE, make a separate bounded, read-only probe of that row's listed route (or a documented non-mutating readiness route), and record the response status, source, and observation timestamp. For POST-only or state-changing surfaces, use a pre-authorized non-mutating contract probe or a timestamped receipt; never trigger an action merely to claim availability. If any required upstream observation is missing, stale, or unusable, present that row as PARTIAL or UNAVAILABLE.

Backend organCatalog routeRecorded state (2026-06-16)
a11oy — llm open-LLM tier routerGET /api/a11oy/v1/llm/tiersLIVE (200)llm_tiers derived from the live tier catalog
killinchu/api/killinchu/v1/mcp/toolsLIVE — 4 tools (cue/halt_drone are 2-person)
a11oy — companion operator / reasoning console/api/a11oy/v1/companion/{ask,act,recommend}LIVE (200) — 3 tools derived from live action routes (no JSON /v1/mcp/tools catalog)
a11oy — immune (Hukulla) egress policy inspectorGET /api/a11oy/v1/immune/gatesLIVE (200, gates-derived) — gates + screen/verdict; the immune screen is the signed /immune/verdict route (there is no separate /screen)
a11oy — command / flagship/api/a11oy/v1/mcp/toolsRegisters a11oy-flagship tools when the JSON catalog is exposed, else one honest a11oy_status tool. Self-heals on the next server restart once the catalog returns 200 — no code change, no fabricated stubs.

Purge note (2026-06-16). The three previously-codenamed backends were purged (their old routes now 404). Hatun-MCP was repointed to the live honest a11oy twins above and verified 200 before wiring. No tool is ever pointed at a 404; where a sub-route does not exist (e.g. /immune/screen) the tool maps to the closest real route (/immune/verdict) and the mapping is disclosed in the adapter docstring and the catalog reason.

Byzantine quorum + BLS aggregate

szl_lambda_quorum fans a governance-critical Λ verdict out to the five backend services and decides under a Byzantine n ≥ 3f+1 quorum (n=5, f=1): ≥ 4 services must be reachable and ≥ 3 must agree. Participating receipts are BLS12-381 aggregated (py_ecc; honest sha256 Merkle-root fallback if the BLS backend is absent). If any organ's policy route is not live, quorum degrades gracefully (n=4 still satisfies n ≥ 3f+1) and discloses the degradation in governance.quorum.


Run locally (stdio)

pip install -r requirements.txt
python -m hatun_mcp.server          # stdio mode for Claude Desktop / Codex

Run hosted (Streamable HTTP)

uvicorn hatun_mcp.server_http:app --host 0.0.0.0 --port 7860
# MCP endpoint:  http://127.0.0.1:7860/mcp   (legacy SSE at /sse)
# Process liveness: http://127.0.0.1:7860/healthz
# Signed-release readiness: http://127.0.0.1:7860/readyz

The DSSE signing key is injected at runtime via the HATUN_MCP_SIGNING_KEY (PEM) operator-managed secret; without it the signer runs in honest PLACEHOLDER mode (clearly labeled, never a fake signature).

/healthz proves that the process and local receipt chain can answer. /readyz is the fail-closed investor/deployment contract: it returns 200 only when the receipt chain verifies and a non-placeholder signing key is active; otherwise it returns 503 with the failing check named. The public server card advertises only the API-key scheme that this server actually implements.

MCP manifest attestation

GET /.well-known/mcp-manifest-attestation returns a cached integrity binding for the exact raw bytes served by GET /.well-known/mcp (all server-card aliases serve those same bytes). It contains a deterministic https://in-toto.io/Statement/v1 with SHA-256 subject digest and the custom predicate type https://szlholdings.com/attestations/mcp-manifest/v1. When the existing P-256 signing key is configured, the statement is carried in a real DSSE envelope whose payloadType is application/vnd.in-toto+json. Without that key, the response is explicitly signing.state=UNSIGNED with dsseEnvelope=null; an empty signature is never presented as signed.

The artifact is built once at process start and accepts no caller-supplied signing payload. It does not mint a Khipu receipt. Its scope is byte integrity only: it does not attest runtime tool parity, upstream availability, or the behavior behind the card. The MCP server card and this well-known route are an SZL DRAFT extension, not a claim of a ratified MCP discovery standard. keyid is only a hint; verifiers must establish trust in the P-256 public key out of band (the same-origin /pubkey route is not an independent trust anchor). Transparency-log inclusion remains explicitly unavailable.

Evaluate the hosted contract

curl -i http://127.0.0.1:7860/healthz
curl -i http://127.0.0.1:7860/readyz
curl -s http://127.0.0.1:7860/api/console-state

/api/console-state (hatun_mcp/state.py) is the read behind the human console at /. The commands above target your locally started server. For a deployment, use its admitted operator-provided origin, not the retired standalone Space host. It is assembled in-request from this process only: the tool catalogue is enumerated from the LIVE FastMCP registry (not a hand-maintained list), the receipt depth and head hash come from the live Khipu chain, and card_parity reports a MEASURED comparison between the published server card and that runtime registry. Anything it cannot read is returned with an honest label (UNAVAILABLE) and no number — there is no seeded snapshot, so the console shows UNAVAILABLE rather than a stale value when a reading fails. It mints no receipt and attests nothing beyond the reading itself.

Record the response status and observation time. Report healthz=200 as Hatun process liveness only. Report readyz=200 as Hatun's repository-defined local receipt-chain and signer readiness only. These checks do not establish killinchu or a11oy organ availability. Before labeling any upstream row LIVE, separately run a bounded, read-only probe of its listed route (or a documented non-mutating readiness route) and record the route, response status, source, and observation timestamp. For POST-only or state-changing surfaces, require a pre-authorized non-mutating contract probe or timestamped receipt instead of triggering an action. If Hatun is ready but an upstream observation is missing, stale, or unusable, report that row as PARTIAL or UNAVAILABLE. Never fall back to the sample client configuration.


MCP client setup

Claude Desktop

The snippets below are SAMPLE local-server configurations. Start the HTTP server first, configure an accepted API key, and replace szl_YOUR_KEY. For a remote deployment, substitute the admitted operator-provided HTTPS MCP URL. Drop examples/claude-desktop-config.json into ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) / %APPDATA%\Claude\claude_desktop_config.json (Windows), replacing szl_YOUR_KEY:

{
  "mcpServers": {
    "hatun-mcp": {
      "command": "npx",
      "args": ["-y", "mcp-remote",
        "http://127.0.0.1:7860/mcp/",
        "--header", "Authorization: Bearer szl_YOUR_KEY"]
    }
  }
}

Codex (~/.codex/config.toml)

[mcp_servers.hatun-mcp]
command = "npx"
args = ["-y", "mcp-remote", "http://127.0.0.1:7860/mcp/",
        "--header", "Authorization: Bearer szl_YOUR_KEY"]

Continue (~/.continue/config.json)

{
  "experimental": {
    "modelContextProtocolServers": [
      {
        "transport": {
          "type": "stdio",
          "command": "npx",
          "args": ["-y", "mcp-remote",
            "http://127.0.0.1:7860/mcp/",
            "--header", "Authorization: Bearer szl_YOUR_KEY"]
        }
      }
    ]
  }
}

Tests

HATUN_MCP_DISABLE_DYNAMIC=true python -m pytest tests/ -q
# tests/test_server.py    — list tools, call a tool, assert response shape
# tests/test_github_estate_snapshot.py — bounded public GitHub observer, mocked provider
# tests/test_quorum.py    — quorum math + threshold edge cases + BLS aggregate
# tests/test_adapters.py  — mocked organ endpoints, adapter wiring + honest gaps
# tests/test_governance.py— Khipu chain, Yuyay gate, PURIQ factor (pre-existing)
# tests/test_http_routes.py — exact-byte card attestation + public HTTP contracts

The server tests also import the estate regression class so the existing explicit-file hosted CI gate exercises it. They verify real in-memory MCP discovery/calls, argument rejection, canonical digest binding, and an ephemeral P-256 signature. Provider responses in these tests are SIMULATED; passing them does not publish the new tool or establish current GitHub/HF health.

python tests/proof_inmemory.py exercises the real in-memory MCP protocol and checks exact static runtime/server-card name parity. The proof disables dynamic catalog probing and receipt-sink forwarding in its own process. CI also runs it from an unrelated working directory to verify the documented direct command.

The Ouroboros loop (doctrine cross-reference)

hatun-mcp does not implement the estate's Ouroboros bounded-recursion kernel itself; its PURIQ orchestrator is a bounded, single-pass per-tool-call flow, not recursion. This section is a doctrine cross-reference plus an honest note on how that flow embodies the loop's receipt-closed identity (receipts.in ≡ receipts.out, already carried in this README).

The canonical definition is the receipt-closed kernel szl-holdings/ouroborossrc/loop-kernel.ts (runLoop): bounded recursion with measurable convergence that MUST terminate on one of four exit conditions — converged | consistent | aborted | budgetExhausted — and emits a governance receipt for every run. The trace is the product.

How hatun-mcp embodies that primitive (in hatun_mcp/puriq.py):

  • Bounded & terminating. Each tool call is a finite pipeline — Yuyay-13 gate → mesh quorum (Byzantine n ≥ 3f+1) → HUKLLA tripwire → Khipu append → DSSE-sign → compose the master-formula scalar — that always terminates within a latency budget and returns a receipt hash. There is no unbounded loop.
  • Receipt-closed. Every call mints a Khipu link on an append-only sha256 DAG and the client receives the receipt hash. That is this repo's live realization of the header identity receipts.in ≡ receipts.out — a metaphor (doctrine, not math), where each signed receipt is fed back into the DAG as an auditable input.

Honesty (Doctrine v11 · 749/14/163): Λ is consumed here as an input scalar in [0,1] and is Conjecture 1 — advisory, never a proven theorem. This is a bounded, terminating governance flow — it makes no perpetual-motion or zero-cost claim.


Doctrine v11 LOCKED — 749 / 14 / 163 · Λ = Conjecture 1 (NOT a theorem) · SLSA L1 honest · L2 verified-provenance on roadmap (L3 not claimed) receipts.in ≡ receipts.out

Signed-off-by: Yachay <yachay@szlholdings.ai> Co-Authored-By: Perplexity Computer Agent <agent@perplexity.ai>

Contributors

Languages

Python

99.2%