diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 93b3516..6848895 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,6 +3,7 @@ name: CI on: + workflow_dispatch: push: branches: [main, master] pull_request: diff --git a/docs/contracts/scp_antigen_mcp_v1.md b/docs/contracts/scp_antigen_mcp_v1.md new file mode 100644 index 0000000..64e4f92 --- /dev/null +++ b/docs/contracts/scp_antigen_mcp_v1.md @@ -0,0 +1,83 @@ +# SCP Antigen MCP contract v1 + +**Version:** 1.0 +**Purpose:** Public specification for the SCP mesh extension MCP server (`antigen_mcp.py`) — antigen transport, shared registry fetch/contribute/apply. Separate from core [scp_mcp_v1.md](scp_mcp_v1.md) to preserve frozen v1.0 core contract. + +**Normative:** Tool names and human-gate semantics below. Network I/O tools live here only — not on core `scp_mcp`. + +--- + +## Transport + +- MCP over **stdio** (typical `mcp.json` entry `scp-antigen`). +- Server name identifier: `SCP-Antigen` (FastMCP) or equivalent. + +--- + +## Tool groups + +### Antigen bundle (P0) + +| Tool | Parameters | Human gate | Notes | +|------|------------|------------|-------| +| `scp_antigen_export` | `patterns_json`, `antigen_id`, optional sign fields | — | Build bundle | +| `scp_antigen_verify` | `bundle_json`, `allowlist?`, `require_signature?` | — | No side effects | +| `scp_antigen_import` | `bundle_json`, `allowlist?`, `require_signature?` | Never auto-merges | Quarantine only | +| `scp_antigen_merge` | `bundle_json`, `approve?` default **false** | **`approve=true` required** | Registry merge | +| `scp_antigen_publish` | `bundle_json`, `seckey_hex?`, `relays?`, `dry_run?` | Operator credentials | Nostr kind 30078 | +| `scp_antigen_discover` | `allowlist?`, `relays?`, filters | Empty allowlist fails closed | Metadata only | +| `scp_antigen_fetch` | `url`, `expected_hash`, `allowlist?`, `l402_token?` | No auto-pay on 402 | HTTPS fetch + verify | + +### Registry mycelium (R3/R4) + +| Tool | Parameters | Human gate | Notes | +|------|------------|------------|-------| +| `scp_fetch_registry` | `source`, `allowlist`, `if_none_match?`, `tls_verify?`, `relays?` | Stages to quarantine only; **`merged` always false** | HTTPS or nostr | +| `scp_contribute_pattern` | `transport`, `patterns_json?`, `raw_content?`, `approve?` default **false**, … | **`approve=true` for publish**; `approve=false` → zero network I/O | R3 contribute | +| `scp_apply_registry_quarantine` | `quarantine_path`, `approve?` default **false** | **`approve=true` for production merge**; dev auto via `SCP_REGISTRY_MERGE_DEV_AUTO=1` | R4 SSOT + projection | + +--- + +## End-to-end mycelium flow (informative) + +```text +scp_fetch_registry (antigen_mcp) → quarantine_path +scp_apply_registry_quarantine approve=true (antigen_mcp) → SSOT + ~/.scp/threat_registry_projection.json +scp_registry_summary / scp_inspect (scp_mcp v1.0 + v1.1) → uses updated projection per load order +``` + +Core inspect load order documented in [scp_mcp_v1.1.md](scp_mcp_v1.1.md). + +--- + +## Environment variables (informative) + +| Variable | Purpose | +|----------|---------| +| `SCP_PATTERN_SSOT_PATH` | pattern_record SSOT store | +| `SCP_THREAT_REGISTRY_PATH` | Override registry/projection path | +| `SCP_REGISTRY_MERGE_DEV_AUTO` | Dev-only auto-merge low-risk patterns | +| `SCP_ANTIGEN_RELAYS` | Default nostr relays | +| `NOSTR_SECKEY` | Publish/discover credentials (operator-gated) | + +--- + +## Security invariants + +- Fetch stages only; merge is separate apply step +- Contribute two-phase consent: proposal (`approve=false`) then publish (`approve=true`) +- No network tools on core `scp_mcp` v1.0 required set +- Allowlists fail closed when empty where specified + +--- + +## Verification + +- **CONTRACT_HASH:** SHA-256 of this file (UTF-8, LF). Vendored in SCP `docs/contracts/`. +- Implementations SHOULD document tool list parity in release notes. + +--- + +## Changelog + +- **v1.0** — Initial antigen mesh contract (SCP-R5 dual-server). diff --git a/docs/contracts/scp_mcp_v1.1.md b/docs/contracts/scp_mcp_v1.1.md new file mode 100644 index 0000000..0d7d569 --- /dev/null +++ b/docs/contracts/scp_mcp_v1.1.md @@ -0,0 +1,62 @@ +# SCP MCP contract v1.1 (optional add-ons) + +**Version:** 1.1 +**Purpose:** Optional read-only registry introspection tools for the SCP core MCP server (`scp_mcp.py`). +**Requires:** [scp_mcp_v1.md](scp_mcp_v1.md) v1.0 tool surface (all nine required tools MUST remain present). + +**Normative:** Tool names, parameters, and JSON shapes below. v1.0-only hosts remain conformant without implementing v1.1. + +--- + +## Transport + +Same as v1.0 — MCP over stdio; server identifier `SCP`. + +--- + +## Tools (optional) + +| Tool | Parameters | Success return | Error return | +|------|------------|----------------|--------------| +| `scp_registry_summary` | none | JSON `{registry_path, sections}` where `sections` maps top-level registry keys to counts; `registry_path` MAY be redacted unless debug env enabled | JSON `{"error": {"code", "message", "details"?}}` | +| `scp_registry_section` | `section: string`, `max_chars?: int` default 2048 | JSON `{section, excerpt, truncated}` — JSON text excerpt of one allowlisted section | JSON error object | + +### Registry resolution (normative) + +Threat registry JSON load order for v1.1 tools and inspect: + +1. `SCP_THREAT_REGISTRY_PATH` — if set and file exists +2. `~/.scp/threat_registry_projection.json` — if exists (post-merge projection) +3. Packaged `scp_threat_registry.json` — ship default + +### `scp_registry_section` constraints + +- Section names MUST match `^[a-z_][a-z0-9_]{0,63}$` +- Section MUST be in allowlist (default: packaged registry top-level keys; override via `SCP_REGISTRY_SECTION_ALLOWLIST` comma-separated) +- Effective excerpt cap: `min(max_chars, 4096)`; `max_chars` MUST be ≥ 1 +- MUST NOT dump full registry in one call + +### Debug metadata + +When `SCP_DEBUG_META=1`, `registry_path` in summary responses MAY include resolved filesystem path. + +--- + +## Security invariants + +- Read-only — no network I/O, no merge, no publish +- No auto-merge or auto-publish on core pipeline +- v1.0 contract unchanged for existing consumers + +--- + +## Verification + +- **CONTRACT_HASH:** SHA-256 of this file (UTF-8, LF). Vendored copy in SCP `docs/contracts/` with hash test. +- v1.0 conformance: all nine v1.0 tools present; v1.1 tools optional extras. + +--- + +## Changelog + +- **v1.1** — Optional registry summary/section; registry load order for inspect loop (SCP-R5).