{
  "$comment": "GENERATED tools[] from MCP_MANIFEST + OUTPUT_SCHEMAS (coderifts-app src/routes/mcp-streamable.js). Do not edit tools by hand; run: node scripts/generate-mcp-json.js --out <path-to-website>/mcp.json. Top-level registry fields (schema_version, name, display_name, description, version, contact, authentication) are hand-written / preserved. Protocol tools/list stays camelCase; this card uses snake_case input_schema / output_schema by conversion.",
  "schema_version": "v1",
  "name": "coderifts",
  "display_name": "CodeRifts — API Governance",
  "description": "Risk-aware API compatibility governance. Before merge: predicts whether an API change will cause a real production problem, who breaks, by what pattern, at what business cost, and whether blocking is justified.",
  "version": "1.0.0",
  "contact": {
    "email": "peter@coderifts.com",
    "url": "https://coderifts.com"
  },
  "authentication": {
    "type": "bearer",
    "description": "API key from https://coderifts.com — set as Authorization: Bearer <key>"
  },
  "tools": [
    {
      "name": "preflight_change_set",
      "description": "Preflight a COMPLETE base→head change set of contract artifacts and return a\ngovernance decision (ALLOW / WARN / REQUIRE_APPROVAL / BLOCK), risk score,\nbreaking-change analysis, and a signed chain-receipt when applicable.\n\nRequires a pending base→head (before/after) contract change you are about to\nact on (merge, deploy, publish, or register tools). No pending change set →\ndo not call this tool.\n\nUse this when:\n- You are about to merge, push, deploy, publish, or register/expose agent tools,\n  AND the change includes ≥1 contract artifact (OpenAPI/Swagger, GraphQL SDL,\n  gRPC/protobuf, AsyncAPI, MCP manifest, or agent tool schemas: type=agent_tools,\n  including before re-registering tools with a runtime).\n- You have (or can assemble) FULL base and head for every changed contract\n  artifact in this set — not a single-file subset when other contract files also\n  change.\n- You need a NEW decision for the CURRENT change; you do not already hold a\n  currently-valid receipt for this exact target/operation.\n- You hold a receipt for a different operation or target than the act you will\n  perform (e.g. ALLOW for merge, now deploying) — re-call with the intended\n  operation; a differently-scoped receipt is not reusable authorization.\n\nDo not use when:\n- The change is documentation-only (README, guides, comments) with no contract\n  artifact content change — do not call any CodeRifts tool.\n- You already hold a signed receipt and only need to check it is authentic and\n  currently valid — use coderifts.verify_receipt instead.\n- You need details of a PREVIOUS decision by decision_id — use\n  coderifts.get_decision_details instead.\n- You want a static 0–100 \"agent readiness\" score for one OpenAPI/MCP file and\n  there is no pending base→head mutate — use coderifts.agent_readiness_score\n  (advanced / opt-in; not one of the three default tools). If that tool is not\n  in your available list, call none of the CodeRifts tools; do not substitute\n  preflight_change_set.\n- You cannot supply both before and after (or base and head) for the artifacts\n  that change — fix the change set first; do not invent empty before specs.\n\nInputs: list of artifacts, each with type, before, after (or equivalent), plus\noptional operation (merge|deploy|tool_call|publish), environment/stakes, and\ncontext. Returns decision, execution_action, risk fields, and chain_receipt when issued.",
      "input_schema": {
        "type": "object",
        "properties": {
          "artifacts": {
            "type": "array",
            "description": "Contract artifacts to analyze together (max 20). Each is { id, type, before, after }.",
            "minItems": 1,
            "maxItems": 20,
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "description": "Caller-chosen id, unique within the bundle"
                },
                "type": {
                  "type": "string",
                  "enum": [
                    "openapi",
                    "graphql",
                    "grpc",
                    "asyncapi",
                    "mcp_manifest",
                    "agent_tools"
                  ]
                },
                "before": {
                  "type": "string",
                  "description": "Prior artifact content (spec/schema/manifest) as a string"
                },
                "after": {
                  "type": "string",
                  "description": "Updated artifact content as a string"
                }
              },
              "required": [
                "id",
                "type",
                "before",
                "after"
              ]
            }
          },
          "context": {
            "type": "object",
            "description": "Optional apply-site context folded into the bundle fingerprint. operation distinguishes merge vs deploy vs publish (and other labels); the server accepts any string for operation (change-set.js) — conventional values below.",
            "properties": {
              "operation": {
                "type": "string",
                "description": "Application operation for this change set (fingerprint + envelope). Server accepts any non-empty string; conventional values: merge, deploy, tool_call, publish. Merge is not deploy is not publish — the receipt/gate must match this label."
              },
              "environment": {
                "type": "string",
                "description": "Target environment (e.g. production, staging, npm) — optional; folded into fingerprint when set."
              },
              "repository": {
                "type": "string",
                "description": "Repository identity (optional; fingerprint context)"
              },
              "branch": {
                "type": "string",
                "description": "Branch name (optional; fingerprint context)"
              },
              "pull_request": {
                "description": "Pull request id when applicable (optional; fingerprint context)",
                "oneOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "number"
                  }
                ]
              },
              "policy_profile": {
                "type": "string",
                "description": "Policy profile name (optional; fingerprint context)"
              }
            }
          },
          "previous_receipt": {
            "type": "string",
            "description": "Optional prior chain receipt token to link"
          },
          "idempotency_key": {
            "type": "string",
            "description": "Optional client key; a repeat with the same key + body replays the original decision (24h)"
          },
          "preflight_mode": {
            "type": "string",
            "enum": [
              "analyze",
              "authorize"
            ],
            "description": "Preflight mode. \"analyze\" = evaluate the change set without minting authorization (no chain_receipt for authorization). \"authorize\" = full path including receipt when configured (requires context.operation). Omitted → analyze (soft default; response sets preflight_mode_defaulted:true). Leaving this field out is a deliberate soft default, not an undeclared capability."
          }
        },
        "required": [
          "artifacts"
        ]
      },
      "annotations": {
        "readOnlyHint": true,
        "openWorldHint": false
      },
      "endpoint": {
        "method": "POST",
        "url": "https://app.coderifts.com/api/v1/preflight"
      },
      "output_schema": {
        "type": "object",
        "description": "Aggregated bundle verdict across contract artifacts (strictest-wins). required holds on every success path including idempotency replay (formatStoredDecision), which does not carry fresh-only fields such as bundle_fingerprint or artifacts. additionalProperties true: additive fields may appear and are not permission. Compatibility rule (single source): https://coderifts.com/schemas/decision-result.v1.consumer.json schema description. Branch on execution_action.",
        "properties": {
          "decision": {
            "type": "string",
            "enum": [
              "ALLOW",
              "WARN",
              "REQUIRE_APPROVAL",
              "BLOCK"
            ]
          },
          "safe_for_agent": {
            "type": "boolean"
          },
          "execution_action": {
            "type": "string",
            "enum": [
              "CONTINUE",
              "CONTINUE_WITH_MONITORING",
              "REQUEST_APPROVAL",
              "STOP"
            ]
          },
          "risk_score": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100
          },
          "breaking_changes": {
            "type": "integer",
            "minimum": 0
          },
          "patterns": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "pattern_sources": {
            "type": [
              "array",
              "null"
            ],
            "description": "Optional. Per-name epistemic provenance for patterns[] (source + evidence_kind + basis). null/absent on pre-provenance stored decisions — never invent []. Empty array means analysed with no named patterns. Closed enums: unknown source/evidence_kind → fail closed for control flow. Full envelope schema: https://coderifts.com/schemas/decision-result.v1.consumer.json",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "name",
                "source",
                "evidence_kind"
              ],
              "properties": {
                "name": {
                  "type": "string",
                  "description": "Pattern name; must appear in patterns when both are carried."
                },
                "source": {
                  "type": "string",
                  "enum": [
                    "contract_diff",
                    "agent_heuristic",
                    "artifact_signal"
                  ],
                  "description": "Where the name came from. Closed set; unknown = fail closed for control flow."
                },
                "evidence_kind": {
                  "type": "string",
                  "enum": [
                    "measured",
                    "derived"
                  ],
                  "description": "measured = contract/artifact measurement with optional row refs; derived = agent heuristic with basis. Closed set; unknown = fail closed for control flow."
                },
                "detected_pattern_indices": {
                  "type": "array",
                  "items": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "description": "Indices into same-response detected_patterns for measured records."
                },
                "basis_codes": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  },
                  "description": "Derived only: untranslated change-engine codes that triggered the heuristic."
                },
                "basis_code_labels": {
                  "type": "array",
                  "items": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "description": "Derived only: parallel to basis_codes. Plain-text sentences from the same CODE_MAP as PR comments (explains inverted oasdiff codes, e.g. response.body.scope.add = field removed). No presentation markers. null at an index means no map entry — do not invent a label."
                },
                "basis_rule_id": {
                  "type": "string",
                  "description": "Derived only: OpenAPI location inspected when no change-engine code applies."
                },
                "rule_id": {
                  "type": "string",
                  "description": "Derived only: stable versioned id of OUR agent rule (e.g. agent.tool_result.shape_drift.v1). Not basis_codes; not on measured records."
                }
              }
            }
          },
          "preflight_mode": {
            "type": "string",
            "enum": [
              "analyze",
              "authorize"
            ],
            "description": "Resolved preflight mode for this response. When the request omitted preflight_mode, this is analyze and preflight_mode_defaulted may be true."
          },
          "preflight_mode_defaulted": {
            "type": "boolean",
            "description": "true only when the caller omitted preflight_mode and soft-default analyze was applied."
          },
          "bundle_fingerprint": {
            "type": "string",
            "pattern": "^sha256:[a-f0-9]{64}$"
          },
          "artifacts": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "evidence": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "decision_result": {
            "type": "object",
            "description": "decision-result.v1 envelope (present when a chain receipt is available). Full schema: https://coderifts.com/schemas/decision-result.v1.consumer.json"
          },
          "meta": {
            "type": "object"
          },
          "control_envelope": {
            "type": "object",
            "description": "Control envelope (control/1.0): decision, safe_for_agent, execution_action, required_action, receipt."
          },
          "required_action_core": {
            "type": "object",
            "description": "Branchable required-action core { type, reason_code, recheck_required } when the stored/fresh envelope carries it."
          },
          "verdict_fingerprint": {
            "type": "string",
            "description": "Verdict fingerprint (sha256:…); mirrors envelope.fingerprint on replay."
          },
          "chain_receipt": {
            "type": "string",
            "description": "Signed chain receipt token when issued (fresh path with signer configured)."
          }
        },
        "required": [
          "decision",
          "execution_action",
          "safe_for_agent"
        ],
        "additionalProperties": true
      }
    },
    {
      "name": "verify_receipt",
      "description": "Verify a CodeRifts signed chain-receipt you ALREADY HOLD: cryptographic\nauthenticity (signature + key id), body binding, and — when lifecycle indices\nare available — whether it is currently valid authorization (not expired,\nsuperseded, or revoked) for a stated operation/target.\n\nUse this when:\n- You already obtained a chain_receipt / receipt token from a prior preflight\n  (or CI artifact) and are about to act (merge/deploy) under that receipt.\n- A contract-gate or policy requires offline/online proof that the receipt is\n  authentic for this change before proceeding.\n- You must distinguish \"signature ok\" from \"currently authorized\" (stale or\n  superseded receipts must not be treated as live approval).\n\nDo not use when:\n- You do not have a receipt yet — call coderifts.preflight_change_set first.\n- You need a NEW decision for a changed base→head set — preflight again;\n  verify_receipt does not re-diff specs.\n- The receipt you hold binds a different operation or target than the one you\n  are about to perform — call coderifts.preflight_change_set for that operation;\n  verify_receipt cannot re-scope or re-issue a decision.\n- You only need human-readable history of an old decision_id without a receipt\n  token — use coderifts.get_decision_details.\n- The change set itself is unknown or incomplete — fix the change set and\n  preflight; do not \"verify\" a placeholder.\n\nInputs: receipt token (required); optional expected target_id, operation, and\nnow-skew policy hooks. Returns { valid, status, currently_authorized (bool|null),\nreason, payload, authz_* }. Branch on currently_authorized; null = not evaluated.",
      "input_schema": {
        "type": "object",
        "description": "Two evaluation modes (schema-documented; no mode discriminator field). SIGNATURE: supply token only — signature + expiry; currently_authorized is null. AUTHORIZATION: also supply intended context (operation, environment, fingerprint, target_id, and/or audience) AND the body_hash-bound decision_result envelope so currently_authorized / authz_status / authz_reason can be evaluated. Token alone is always accepted; omitting the envelope when context fields are present yields a signature verdict plus fail-closed authorization (currently_authorized false), not a schema reject.",
        "properties": {
          "token": {
            "type": "string",
            "description": "The chain receipt token (base64url(body).base64url(signature))"
          },
          "operation": {
            "type": "string",
            "description": "Intended operation the receipt must authorize (conventional: merge|deploy|tool_call|publish). Triggers authorization evaluation when non-empty; supply decision_result for full scope binding."
          },
          "target_id": {
            "type": "string",
            "description": "Intended apply-site target the receipt must bind"
          },
          "environment": {
            "type": "string",
            "description": "Intended environment (e.g. production) — must match the receipt"
          },
          "fingerprint": {
            "type": "string",
            "description": "Intended change fingerprint — must equal the receipt fp"
          },
          "audience": {
            "type": "string",
            "description": "Intended audience — must match the receipt"
          },
          "decision_result": {
            "type": "object",
            "description": "The body_hash-bound decision envelope (carries operation/target/decision). Required for a meaningful AUTHORIZATION evaluation of scope; without it, intended context alone fails closed on authorization (currently_authorized false) while signature status remains independent.",
            "additionalProperties": true
          }
        },
        "required": [
          "token"
        ]
      },
      "annotations": {
        "readOnlyHint": true,
        "openWorldHint": false
      },
      "endpoint": {
        "method": "POST",
        "url": "https://app.coderifts.com/api/v1/verify-receipt"
      },
      "output_schema": {
        "type": "object",
        "description": "Receipt signature/status plus optional authorization layer. additionalProperties true: additive fields may appear and are not permission. Envelope compatibility when a decision_result is supplied: https://coderifts.com/schemas/decision-result.v1.consumer.json schema description (single source).",
        "properties": {
          "valid": {
            "type": "boolean",
            "description": "true iff status is VERIFIED_CURRENT or RETIRED_KEY_VALID_AT_ISSUE"
          },
          "status": {
            "type": "string",
            "enum": [
              "VERIFIED_CURRENT",
              "VERIFIED_EXPIRED",
              "VERIFIED_WRONG_AUDIENCE",
              "VERIFIED_WRONG_ENVIRONMENT",
              "VERIFIED_SUPERSEDED",
              "VERIFIED_SCOPE_MISMATCH",
              "UNKNOWN_KEY",
              "RETIRED_KEY_VALID_AT_ISSUE",
              "INVALID_SIGNATURE",
              "MALFORMED",
              "UNSUPPORTED_VERSION",
              "REGISTRY_UNREACHABLE"
            ]
          },
          "reason": {
            "type": [
              "string",
              "null"
            ]
          },
          "payload": {
            "type": "object"
          },
          "currently_authorized": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Whether the receipt currently authorizes the intended operation/target/fp (§106). null means authorization could not be evaluated (e.g. no intended context) — not unauthorized and not authorized."
          },
          "authz_reason": {
            "type": "string",
            "description": "When currently_authorized=false: the deny reason (operation_mismatch, decision_not_allow, superseded, expired, target_mismatch, environment_mismatch, …)"
          },
          "authz_status": {
            "type": "string",
            "description": "Authorization-level status (VERIFIED_WRONG_ENVIRONMENT / VERIFIED_SUPERSEDED / VERIFIED_SCOPE_MISMATCH / …)"
          },
          "authz_state": {
            "type": "string",
            "description": "Lifecycle state from isCurrentlyAuthorized when authorization is evaluated (optional; omitted when currently_authorized is null)"
          },
          "authz_note": {
            "type": "string",
            "description": "Present when no intended context supplied: status reflects signature+expiry only"
          }
        },
        "required": [
          "valid",
          "status",
          "currently_authorized"
        ],
        "additionalProperties": true
      }
    },
    {
      "name": "get_decision_details",
      "description": "Retrieve a PAST CodeRifts decision by decision_id (or fingerprint): full\nreport payload, breaking changes list, scores, and linked receipt metadata\nif stored.\n\nUse this when:\n- You have a decision_id (or fingerprint) from a previous preflight, PR\n  comment, or CI log and need to inspect or explain that past decision.\n- You are auditing why a prior ALLOW/WARN/BLOCK was issued.\n- You are NOT requesting a new analysis of current before/after specs.\n\nDo not use when:\n- You need a decision for the CURRENT uncommitted or PR head change set —\n  call coderifts.preflight_change_set with the current artifacts.\n- You hold a receipt token and only need cryptographic/lifecycle verification —\n  use coderifts.verify_receipt.\n- You have no decision_id/fingerprint — run preflight first to create one.\n\nInputs: at least one of decision_id (preferred) or fingerprint is required\n(empty {} is rejected by the server as INVALID_INPUT). Returns the stored\ndecision document or not_found.",
      "input_schema": {
        "type": "object",
        "properties": {
          "decision_id": {
            "type": "string",
            "minLength": 1,
            "description": "The decision_id from a prior decision_result envelope. Provide this and/or fingerprint (at least one non-empty string required)."
          },
          "fingerprint": {
            "type": "string",
            "minLength": 1,
            "description": "A verdict fingerprint (sha256:...); returns the latest matching decision. Provide this and/or decision_id (at least one non-empty string required)."
          }
        },
        "minProperties": 1,
        "additionalProperties": false
      },
      "annotations": {
        "readOnlyHint": true,
        "openWorldHint": false
      },
      "endpoint": {
        "method": "POST",
        "url": "https://app.coderifts.com/api/v1/decisions/lookup"
      },
      "output_schema": {
        "type": "object",
        "description": "A stored CodeRifts decision: the original decision_result.v1 envelope + lookup meta. Retrieval-path control fields (safe_for_agent/execution_action/verdict_fingerprint/control_envelope) mirror the fresh preflight response and are present only when the stored envelope carries their source field. additionalProperties true: additive fields may appear and are not permission. Compatibility rule (single source): https://coderifts.com/schemas/decision-result.v1.consumer.json schema description.",
        "properties": {
          "decision": {
            "type": "string",
            "enum": [
              "ALLOW",
              "WARN",
              "REQUIRE_APPROVAL",
              "BLOCK"
            ]
          },
          "safe_for_agent": {
            "type": "boolean"
          },
          "execution_action": {
            "type": "string",
            "enum": [
              "CONTINUE",
              "CONTINUE_WITH_MONITORING",
              "REQUEST_APPROVAL",
              "STOP"
            ]
          },
          "verdict_fingerprint": {
            "type": "string"
          },
          "control_envelope": {
            "type": "object",
            "description": "Control envelope (control/1.0) derived from the stored decision_result."
          },
          "required_action_core": {
            "type": "object",
            "description": "Branchable required-action core { type, reason_code, recheck_required } when present on the envelope."
          },
          "risk_score": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100
          },
          "breaking_changes": {
            "type": "integer",
            "minimum": 0
          },
          "patterns": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "decision_result": {
            "type": "object",
            "description": "decision-result.v1 envelope (present when a chain receipt is available). Full schema: https://coderifts.com/schemas/decision-result.v1.consumer.json"
          },
          "meta": {
            "type": "object",
            "properties": {
              "decision_id": {
                "type": "string"
              },
              "source": {
                "type": "string"
              },
              "created_at": {
                "type": "string"
              },
              "retrieval_mode": {
                "type": "string",
                "enum": [
                  "stored"
                ]
              }
            },
            "additionalProperties": true
          }
        },
        "required": [
          "decision_result",
          "meta"
        ],
        "additionalProperties": true
      }
    }
  ]
}
