## Keyboard shortcuts

Press `←` or `→` to navigate between chapters

Press `S` or `/` to search in the book

Press `?` to show this help

Press `Esc` to hide this help

# MCP Tool Reference

The MCP server provides 122 tools organized by category.

## Cross-Harness Discovery (RFC #113)

Three small tools let any MCP client — Claude Code, Cursor, Codex, vanilla Agents SDK — ground itself and reach the routing layer without depending on the `initialize` instructions block. Call them at session start.

### check_context

Cheap, unauthenticated probe of session grounding. Reads local CLI config only — no platform calls. Returns:

    {
      "connected": true,
      "active_system": {"id": "sys-1", "name": "Primary"},
      "active_framework_id": "nist-800-53-r5",
      "suggested_next": "Ready. Call `start_task` with an `intent_verb` to route the user's request to a workflow.",
      "pending_attention": {}
    }

`suggested_next` is deterministic and tells the agent exactly what to do given current state — call `pretorin login`, call `list_systems`, set a framework, or proceed with `start_task`.

Parameters: None.

When to call: Once at session start. Always safe; never makes a platform call.

### list_tools

Compact catalog of every available tool. Returns one short record per tool:

    {
      "total": 122,
      "tier_counts": {"default": 8, "workflow": 12, "reference": 91, "recipe": 11},
      "tools": [
        {"name": "check_context", "purpose": "Cheap, unauthenticated probe of session grounding", "tier": "default", "requires_workflow": false},
        ...
      ]
    }

The full payload fits in roughly 100 lines — far smaller than fetching every tool’s `inputSchema`. Tier classification:

Tier | Meaning
--- | ---
`default` | Always advertised. Minimum surface to ground a session and route a task.
`reference` | Read-only browsing of frameworks, controls, systems, recipes. Safe without prior routing.
`workflow` | Requires prior `start_task` context. Calling without it raises `WorkflowRoutingError`.
`recipe` | Dynamic per-recipe-script tools (`recipe_<id>__<script>`).

Parameters: None.

When to call: Once at session start (or anytime “what’s available?” comes up).

### get_instructions

Returns the server’s routing instructions as a regular tool response. Mirrors the text the MCP `initialize` handshake advertises in the `instructions` field, for harnesses (Cursor, Codex, vanilla Agents SDK) that don’t render that text to the agent.

Parameters: None.

When to call: If the agent didn’t receive routing rules via the `initialize` handshake, or wants to re-read them mid-session.

## Routing Errors (errors-as-instructions)

Workflow-tier tools require an active routing context — either an active system/framework set via `pretorin context set`, or the context that `start_task` resolves. Calling a workflow write without context returns a structured error payload, not just plain text:

    {
      "error": "workflow_required",
      "message": "No active system/framework context. Call start_task with an intent_verb to route the request to the right workflow, or run `pretorin context set --system <id> --framework <id>` in the terminal.",
      "routing_hint": {
        "reason": "no_active_context",
        "next_action": "call_start_task",
        "missing": ["system_id", "framework_id"],
        "suggested_intent_verb": "collect_evidence"
      }
    }

The response carries `isError=true` so agents that only check the error flag still surface the failure, but the parseable body tells them exactly which `start_task` call to make. This means routing rules live in the protocol, not the preamble — harnesses that ignore `instructions` still see the rules in the error payload they have to read anyway.

Evidence and narrative producer writes add one more guardrail: `create_evidence`, `create_evidence_batch`, and `update_narrative` require `recipe_context_id` from `start_recipe`. Missing recipe context returns `recipe_required` with a `recipe_gap` before scope resolution, so agents converge on `start_task` → source preflight → `start_recipe` → write.

`suggested_intent_verb` is set when the called tool has a registered mapping (see `_TOOL_TO_INTENT_VERB` in `src/pretorin/mcp/server.py`). Every tool in `WORKFLOW_TIER` has one; tools added to that set without a mapping will fail the sync test in CI.

## Workflow Schema Bundling

When the agent calls `get_workflow`, the response includes `required_tool_schemas` — the full MCP `Tool` definitions for every tool the workflow body references:

    {
      "id": "single-control",
      "manifest": { "..." },
      "body": "## Single Control Update\n\n...",
      "required_tool_schemas": [
        {"name": "create_evidence", "description": "...", "inputSchema": {...}},
        {"name": "update_narrative", "description": "...", "inputSchema": {...}},
        ...
      ]
    }

Single round trip equips the agent. Schemas are response data — agents can read them as reference regardless of whether their harness supports dynamic tool registration.

## Telemetry

The server emits structured telemetry events to stderr so MCP hosts can capture them through their existing log pipeline. Each event is one line:

    PRETORIN_TELEMETRY_EVENT {"ts": 1747249200.12, "event_type": "workflow_routing_required", "tool": "create_evidence", "reason": "no_active_context", "missing": ["system_id", "framework_id"], "suggested_intent_verb": "collect_evidence"}
    PRETORIN_TELEMETRY_EVENT {"ts": 1747249200.99, "event_type": "recipe_required", "tool": "create_evidence", "reason": "agent write attempted without recipe_context_id", "requested_evidence_type": "code_snippet", "suggested_next": "call_start_task_then_start_recipe"}

Events emitted:

event_type | When
--- | ---
`start_task_succeeded` | A `start_task` call completed successfully (the canonical-path signal).
`workflow_routing_required` | A write tool raised `WorkflowRoutingError` (the bypass signal).
`recipe_required` | An evidence or narrative producer write returned the structured recipe-context guardrail before scope resolution.

For the post-recipe producer path, compute the combined bypass rate as:

    (workflow_routing_required + recipe_required) / start_task_succeeded

When your log pipeline can group by MCP session, count only bypass events that did not have the expected preceding canonical calls in that same session: `start_task` for `workflow_routing_required`, and `start_task` → source preflight → `start_recipe` for `recipe_required`. The `recipe_required` event carries only non-content shape data such as evidence type, item count, narrative length, and `suggested_next`; it must not include artifact content, narrative text, evidence ids, control ids, or source excerpts.

Per RFC #113 and issue #121, this combined bypass data gates any phase-4 default-surface cull or capability-negotiation work.

Opt-out: set `PRETORIN_MCP_TELEMETRY_DISABLED=1` in the environment before starting the MCP server. Local-only — no PII or content leaves the user’s machine.

## Common Write-Side Parameters

Most write-side tools (evidence, narratives, notes, control status, monitoring events) accept two shared audit-trail flags. Both default to `false` and should only be set when the calling agent has a deliberate reason to bypass the corresponding guardrail:

- `allow_scope_override` — Permit a write outside the active system/framework context.
- `allow_unverified_sources` — Permit a write when source attestation shows a mismatch.

Where listed below as “(audit-trail flags)”, a tool accepts both fields. MCP agent evidence and narrative writes require `recipe_context_id` returned by `start_recipe`; writes without one return a structured `recipe_required` error.

## Task Routing

### start_task

Route a user prompt to the right workflow. Call this FIRST whenever the user references compliance work (a control, system, framework, questionnaire, or campaign). The calling agent extracts entities from the user prompt and supplies them as structured args; pretorin applies deterministic rules to pick a workflow and bundles the platform read-state (workflow_state, compliance_status, pending items) into the response. The agent then reads the selected workflow’s body via `get_workflow` and follows it.

The one exception is pure reference questions (“show me AC-2”, “list frameworks”) — those go directly to the read-side tools without `start_task`.

Parameters:

- `entities` (required) — Structured entities extracted from the user prompt. Required sub-fields: `intent_verb` (one of `work_on`, `collect_evidence`, `draft_narrative`, `answer`, `campaign`, `inspect_status`) and `raw_prompt` (original verbatim text). Optional: `system_id`, `framework_id`, `control_ids`, `scope_question_ids`, `policy_question_ids`.
- `active_system_id` (optional) — The user’s active CLI context system_id, if any. Used to detect cross-system writes.
- `active_framework_id` (optional) — The user’s active CLI context framework_id, if any. Used by `inspect_status` when the user asks for current status without naming a framework.
- `skip_inspect` (optional) — Skip the server-side platform reads when the calling agent already has fresh state. Default: `false`

Returns: Selected workflow id, resolved scope (system/framework/items), platform-state bundle, and `suggested_capture_plan` for source/recipe preflight when the workflow produces evidence or narratives.

## Framework & Control Reference

These tools are read-only and available to all authenticated users.

### list_frameworks

List all available compliance frameworks.

Parameters: None

Returns: List of frameworks with ID, title, version, tier, and control counts.

### get_framework

Get detailed metadata about a specific framework including AI context (purpose, target audience, regulatory context).

Parameters:

- `framework_id` (required) — e.g., `nist-800-53-r5`, `fedramp-moderate`

Returns: Framework details including description, version, OSCAL version, and dates.

### list_control_families

List control families for a framework with AI context (domain summary, risk context, implementation priority).

Parameters:

- `framework_id` (required)

Returns: List of control families with ID, title, class, and control count.

### list_controls

List controls for a framework, optionally filtered by family.

Parameters:

- `framework_id` (required)
- `family_id` (optional) — Family IDs are slugs like `access-control`, not short codes. CMMC families include a level suffix (e.g., `access-control-level-2`).

Returns: List of controls with ID, title, and family.

### get_control

Get detailed control information including AI guidance (summary, control intent, evidence expectations, implementation considerations, common failures, complexity).

Parameters:

- `framework_id` (required)
- `control_id` (required) — NIST/FedRAMP: zero-padded (`ac-01`). CMMC: dotted (`AC.L2-3.1.1`).

Returns: Control details including parameters, parts, and enhancement count.

### get_controls_batch

Get detailed control data for many controls in one framework-scoped request.

Parameters:

- `framework_id` (required)
- `control_ids` (optional) — List of canonical control IDs; omit to retrieve all controls in the framework

Returns: Full control detail records for the requested controls.

### get_control_references

Get reference information including statement, guidance, objectives, and related controls.

Parameters:

- `framework_id` (required)
- `control_id` (required)

Returns: Statement, guidance, objectives, parameters, and related controls.

## Systems

### list_systems

List systems in the current organization.

Parameters: None

Returns: System IDs, names, and summary metadata.

### get_cli_status

Return the local Pretorin CLI version status, including update availability and upgrade guidance for MCP hosts and agents.

Parameters:

- `force` (optional) — Bypass local cache and re-check PyPI for the latest version. Default: `false`

Returns: Current version, latest version, update available flag, and upgrade instructions.

### get_source_manifest

Get the resolved source manifest for a system and evaluate it against currently detected sources. Shows which external sources (git, cloud, HRIS, etc.) are required, recommended, or optional, and whether each is currently satisfied.

Parameters:

- `system_id` (optional) — System ID or name

Returns: Source manifest with per-source satisfaction status. Returns null manifest if none is configured.

### get_system

Get system metadata including attached frameworks and security impact level.

Parameters:

- `system_id` (required) — System ID or name

Returns: System metadata.

### list_connected_sources

List source connections bound to a system for recipe preflight. Older platform deployments return `availability: "unknown"` instead of blocking recipe discovery.

Parameters:

- `system_id` (optional) — Defaults to active scope

Returns: Source availability plus normalized source rows (`kind`, `connected`, `identifier`, `binding_role`, `last_checked`, `probe_status`).

### get_compliance_status

Get framework progress and implementation posture for a system.

Parameters:

- `system_id` (required) — System ID or friendly system name

Returns: Framework status summaries and progress metrics.

## Evidence Management

### search_evidence

Search current evidence items.

Parameters:

- `system_id` (optional) — System ID or friendly system name. When omitted, the active CLI scope is used if available.
- `control_id` (optional) — Filter by control
- `framework_id` (optional) — Filter by framework
- `limit` (optional) — Maximum number of results. Default: `20`

Returns: Matching evidence items. The server uses the same compatibility search path as the CLI for deployments that only expose system-scoped evidence routes.

### create_evidence

Upsert evidence on the platform (find-or-create by default). If `dedupe` is true, exact matching evidence in the active system/framework scope is reused; otherwise a new record is created.

Parameters:

- `name` (required)
- `description` (required) — Short human summary of what the evidence demonstrates
- `artifact_content` (required) — Markdown body containing the actual evidence artifact
- `evidence_type` (required) — Must be one of the canonical evidence types
- `system_id` (optional) — Defaults to active scope
- `control_id` (optional)
- `framework_id` (optional)
- `dedupe` (optional) — Default: `true`
- `code_file_path` (optional) — Path to source file (relative to workspace root)
- `code_line_numbers` (optional) — Line range (e.g., `10-25`)
- `code_snippet` (optional) — Relevant code excerpt
- `code_repository` (optional) — Git repository URL
- `code_commit_hash` (optional) — Git commit hash
- `source_uri`, `source_label`, `source_locator`, `source_excerpt`, `capture_method` (optional) — Structured provenance inputs. If omitted, the handler derives safe defaults from code context or active scope.
- `recipe_context_id` (required) — Active recipe execution context from `start_recipe`; evidence is stamped `producer_kind='recipe'` automatically.
- `allow_scope_override`, `allow_unverified_sources` (optional, audit-trail flags)

Returns:

- `evidence_id`
- `created` — true if new, false if reused
- `linked` — whether control/system link succeeded
- `match_basis` — `exact_name_desc_type_control_framework` or `none`

### create_evidence_batch

Create and link multiple evidence items within one system/framework scope in a single request.

Parameters:

- `items` (required) — Array of evidence payloads. Each item: `name`, `description`, `artifact_content`, `control_id`, `evidence_type` (required); optional `relevance_notes`, `code_file_path`, `code_line_numbers`, `code_snippet`, `code_repository`, `code_commit_hash`, `source_uri`, `source_label`, `source_locator`, `source_excerpt`, `capture_method`.
- `system_id` (optional) — Defaults to active scope
- `framework_id` (optional) — Defaults to active scope
- `recipe_context_id` (required) — Active recipe execution context from `start_recipe`; every item in the batch is stamped `producer_kind='recipe'`. All items share the same context — per-item context variation is not supported in v1.
- `allow_scope_override`, `allow_unverified_sources` (optional, audit-trail flags)

Returns: Batch creation summary with per-item results and created evidence IDs.

### link_evidence

Link an existing evidence item to a control.

Parameters:

- `evidence_id` (required)
- `control_id` (required)
- `system_id` (optional) — Defaults to active scope
- `framework_id` (optional)
- `allow_scope_override`, `allow_unverified_sources` (optional, audit-trail flags)

Returns: Link confirmation.

### link_evidence_to_cci_implementation

Link an existing evidence item to a per-system CCI implementation row. Use when you already have the CCI implementation UUID (from `get_cci_implementation` or `get_cci_status`).

Parameters:

- `evidence_id` (required)
- `cci_implementation_id` (required)
- `system_id` (optional) — Defaults to active scope
- `override_system_mismatch` (optional, default `false`) — Permit cross-system attachment
- `override_reason` (optional) — Required when `override_system_mismatch` is true

Returns: Link confirmation with `link_summary.cci_implementation_id`.

### link_evidence_to_stig_rule_workflow

Link an existing evidence item to a STIG rule workflow. Lazy-creates the workflow row if none exists yet for `(system, stig_rule)`. Use to attach remediation proof, mitigating-control documentation, or waiver-justification artifacts to a failing rule.

Parameters:

- `evidence_id` (required)
- `stig_rule_id` (required) — STIG catalog rule UUID
- `system_id` (optional) — Defaults to active scope
- `override_system_mismatch` (optional, default `false`)
- `override_reason` (optional) — Required when `override_system_mismatch` is true

Returns: Link confirmation with `link_summary.stig_rule_workflow_id`.

### upload_evidence

Upload a file as evidence to the platform (system-scoped, requires WRITE access).

Parameters:

- `file_path` (required) — Absolute path to the file to upload
- `name` (required) — Evidence name
- `system_id` (optional) — Defaults to active scope
- `evidence_type` (optional) — Default: `other`
- `description` (optional) — Evidence description
- `control_id` (optional)
- `framework_id` (optional)
- `allow_scope_override`, `allow_unverified_sources` (optional, audit-trail flags)

Returns: Uploaded evidence record.

### delete_evidence

Delete an evidence item from the platform (system-scoped, requires WRITE access).

Parameters:

- `evidence_id` (required) — The evidence item ID to delete
- `system_id` (optional) — Defaults to active scope
- `framework_id` (optional) — Defaults to active scope
- `allow_scope_override` (optional, audit-trail flag)

Returns: Deletion confirmation.

### get_narrative

Get the current narrative record for a control.

Parameters:

- `control_id` (required)
- `system_id` (optional) — Defaults to active scope
- `framework_id` (optional) — Defaults to active scope
- `allow_scope_override`, `allow_unverified_sources` (optional, audit-trail flags)

Returns: Narrative text, status, and AI confidence metadata.

## Implementation Context

### get_control_context

Get rich context for a control including AI guidance, statement, objectives, scope status, and current implementation details.

Parameters:

- `control_id` (required)
- `system_id` (optional) — Defaults to active scope
- `framework_id` (optional) — Defaults to active scope

Returns: Combined control metadata and implementation details.

### get_scope

Get system scope and policy information including excluded controls and Q&A responses.

Parameters:

- `system_id` (required)
- `framework_id` (required)

Returns: Scope narrative, excluded controls, Q&A responses, and scope status.

### patch_scope_qa

Apply partial scope questionnaire updates for a system/framework.

Parameters:

- `system_id` (required)
- `framework_id` (required)
- `updates` (required) — Non-empty list of `{question_id, answer}` objects

Returns: Updated scope questionnaire state, including the saved responses.

### list_org_policies

List organization policies available for questionnaire work.

Parameters: None

Returns: Policy summaries including `id`, `name`, template linkage, and questionnaire status.

### get_org_policy_questionnaire

Get the canonical questionnaire state for one organization policy.

Parameters:

- `policy_id` (required)

Returns: Policy metadata, saved answers, and the merged template/question set when available.

### patch_org_policy_qa

Apply partial questionnaire updates for one organization policy.

Parameters:

- `policy_id` (required)
- `updates` (required) — Non-empty list of `{question_id, answer}` objects

Returns: Updated organization policy questionnaire state.

### get_control_implementation

Get implementation details for a control in a system.

Parameters:

- `control_id` (required)
- `system_id` (optional) — Defaults to active scope
- `framework_id` (optional) — Defaults to active scope
- `allow_scope_override`, `allow_unverified_sources` (optional, audit-trail flags)

Returns: Current status, narrative, evidence count, and notes metadata.

### get_control_notes

Get notes for a control implementation.

Parameters:

- `control_id` (required)
- `system_id` (optional) — Defaults to active scope
- `framework_id` (optional)

Returns: Note list with `total` count.

### update_narrative

Push a narrative text update produced by a narrative recipe.

Parameters:

- `control_id` (required)
- `narrative` (required) — Must be auditor-ready markdown (no headings, 2+ rich elements, 1+ structural element, no images)
- `system_id` (optional) — Defaults to active scope
- `framework_id` (optional) — Defaults to active scope
- `is_ai_generated` (optional) — Default: `false`
- `recipe_context_id` (required) — Active narrative-producing recipe context from `start_recipe`
- `evidence_ids` (required) — Evidence ids cited by the narrative
- `allow_scope_override`, `allow_unverified_sources` (optional, audit-trail flags)

Returns: Update confirmation.

### add_control_note

Add a note for unresolved gaps or manual follow-up actions. Content is plain text (no markdown validation required).

Parameters:

- `control_id` (required)
- `content` (required)
- `system_id` (optional) — Defaults to active scope
- `framework_id` (optional) — Defaults to active scope
- `allow_scope_override`, `allow_unverified_sources` (optional, audit-trail flags)

Returns: The created note record.

### resolve_control_note

Resolve, unresolve, or update an existing control note. Use this to clear blocking notes so control status can advance. Resolving a note requires a `resolution_note` justification for the audit trail.

Parameters:

- `control_id` (required)
- `note_id` (required)
- `system_id` (optional) — Defaults to active scope
- `framework_id` (optional) — Defaults to active scope
- `is_resolved` (optional) — Default: `true`
- `resolution_note` (required when resolving) — Explain why the note can be closed; stored as the resolution audit trail and cascaded to linked RFIs/findings
- `content` (optional) — Updated note content
- `is_pinned` (optional)
- `allow_scope_override`, `allow_unverified_sources` (optional, audit-trail flags)

Returns: The updated note record.

## Compliance Updates

### update_control_status

Start or reopen authoring for a control.

Parameters:

- `control_id` (required)
- `status` (required) — `in_progress`
- `system_id` (optional) — Defaults to active scope
- `framework_id` (optional)
- `allow_scope_override`, `allow_unverified_sources` (optional, audit-trail flags)

CLI/MCP callers cannot set `ready_to_approve`, `implemented`, or `not_applicable`; those decisions happen in the Pretorin UI by a human.

Returns: Status update confirmation.

### push_monitoring_event

Create a monitoring event for a system.

Parameters:

- `title` (required)
- `system_id` (optional) — Defaults to active scope
- `framework_id` (optional) — Defaults to active scope
- `severity` (optional) — `critical`, `high`, `medium`, `low`, `info`. Default: `medium`
- `event_type` (optional) — `security_scan`, `configuration_change`, `access_review`, `compliance_check`. Default: `security_scan`
- `control_id` (optional)
- `description` (optional)
- `allow_scope_override`, `allow_unverified_sources` (optional, audit-trail flags)

Returns: The created monitoring event.

### generate_control_artifacts

Generate read-only AI drafts for a control narrative and evidence-gap assessment.

Parameters:

- `system_id` (required)
- `control_id` (required)
- `framework_id` (required)
- `working_directory` (optional) — Local workspace path for code-aware drafting
- `model` (optional) — Model override

Returns: Draft narrative text plus evidence-gap analysis. Does not write to the platform.

To persist approved evidence or narrative changes, first open the matching recipe context; `create_evidence` and `update_narrative` require `recipe_context_id`.

## Workflow State & Analytics

### get_workflow_state

Get the lifecycle state for a system+framework, showing which stage needs work next (scope, policies, controls, evidence).

Parameters:

- `system_id` (required)
- `framework_id` (required)

Returns: Current workflow stage, completion percentages, and next recommended action.

### get_analytics_summary

Get a lightweight system progress snapshot.

Parameters:

- `system_id` (required)
- `framework_id` (required)

Returns: Scope completion, policy completion, control coverage, and evidence gaps.

### get_family_analytics

Get per-family breakdown with narrative coverage, evidence coverage, and status distribution.

Parameters:

- `system_id` (required)
- `framework_id` (required)

Returns: Per-family metrics.

### get_policy_analytics

Get per-policy breakdown with answer completion and review status.

Parameters:

- `policy_id` (required)

Returns: Per-policy completion metrics.

## Family Operations

### get_pending_families

Identify which control families need work.

Parameters:

- `system_id` (required)
- `framework_id` (required)

Returns: Families with counts of pending vs total controls.

### get_family_bundle

Get all controls in one family with status, narrative presence, evidence presence, and note counts.

Parameters:

- `system_id` (required)
- `family_id` (required)
- `framework_id` (required)

Returns: Complete family bundle with per-control details.

### trigger_family_review

Trigger AI review of all controls in a family. Takes 2-4 minutes for large families.

Parameters:

- `system_id` (required)
- `family_id` (required)
- `framework_id` (required)

Returns: Review job ID for polling.

### get_family_review_results

Poll family review results.

Parameters:

- `system_id` (required)
- `job_id` (required)

Returns: Aggregated findings with severity, affected control IDs, and recommended fixes.

## Scope Workflow

### get_pending_scope_questions

Get only unanswered scope questions (lightweight).

Parameters:

- `system_id` (required)
- `framework_id` (required)

Returns: List of unanswered questions with IDs.

### get_scope_question_detail

Get guidance, tips, and example responses for a specific scope question.

Parameters:

- `system_id` (required)
- `question_id` (required)
- `framework_id` (required)

Returns: Question text, guidance, tips, and example answers.

### answer_scope_question

Answer one scope question.

Parameters:

- `system_id` (required)
- `question_id` (required)
- `answer` (required)
- `framework_id` (required)

Returns: Updated question state.

### trigger_scope_generation

Trigger AI generation of scope document from answered questions. By default the same durable job also runs an AI review after generation.

Parameters:

- `system_id` (required)
- `framework_id` (required)
- `include_review` (optional) — Run AI review after generation in the same job. Default: `true`

Returns: Generation job ID for polling.

### trigger_scope_review

Trigger AI review of scope answers.

Parameters:

- `system_id` (required)
- `framework_id` (required)

Returns: Review job ID for polling.

### get_scope_review_results

Poll for structured scope review findings.

Parameters:

- `system_id` (required)
- `job_id` (required)

Returns: Findings with severity levels and recommended fixes.

## Policy Workflow

### get_pending_policy_questions

Get only unanswered policy questions.

Parameters:

- `policy_id` (required)

Returns: List of unanswered questions.

### get_policy_question_detail

Get guidance, tips, and examples for a specific policy question.

Parameters:

- `policy_id` (required)
- `question_id` (required)

Returns: Question text, guidance, and example answers.

### answer_policy_question

Answer one policy question.

Parameters:

- `policy_id` (required)
- `question_id` (required)
- `answer` (required)

Returns: Updated question state.

### get_policy_workflow_state

Get per-policy workflow state including completion, generation, and review status.

Parameters:

- `policy_id` (required)

Returns: Policy workflow state.

### trigger_policy_generation

Trigger AI generation of policy document from answered questions. By default the same durable job also runs an AI review after generation.

Parameters:

- `policy_id` (required)
- `system_id` (optional) — System ID for scope context
- `include_review` (optional) — Run AI review after generation in the same job. Default: `true`

Returns: Generation job status.

### trigger_policy_review

Trigger AI review of policy answers/document.

Parameters:

- `policy_id` (required)

Returns: Review job ID for polling.

### get_policy_review_results

Poll for structured policy review findings.

Parameters:

- `policy_id` (required)
- `job_id` (required)

Returns: Findings with severity levels and recommended fixes.

## Campaign Operations

Campaigns enable bulk compliance operations with checkpoint persistence and lease-based concurrency.

### prepare_campaign

Prepare a workflow-aligned campaign run with a platform state snapshot.

Parameters:

- `domain` (required) — `controls`, `policy`, or `scope`
- `mode` (required) — Campaign mode for the selected domain
- `system_id` (optional) — Defaults to active scope
- `framework_id` (optional) — Defaults to active scope
- `family_id` (optional) — Target family for control campaigns
- `control_ids` (optional) — Explicit control IDs to include
- `all_controls` (optional) — Include all controls. Default: `false`
- `artifacts` (optional) — Artifact type: `narratives`, `evidence`, or `both`. Default: `both`
- `review_job` (optional) — Family review job ID for `review-fix` mode
- `policy_ids` (optional) — Explicit policy IDs to include
- `all_incomplete` (optional) — Include all incomplete items. Default: `false`
- `apply` (optional) — Apply proposals immediately. Default: `false`
- `output` (optional) — Output format: `auto`, `live`, `compact`, `json`. Default: `json`
- `checkpoint_path` (optional) — Local checkpoint file path
- `working_directory` (optional) — Working directory for executors
- `concurrency` (optional) — Parallel execution limit. Default: `4`
- `max_retries` (optional) — Retry limit per item. Default: `2`

Returns: Campaign checkpoint with item list and metadata.

### claim_campaign_items

Claim items for drafting with TTL-based leases. Safe for fan-out to multiple agents.

Parameters:

- `checkpoint_path` (required) — Local campaign checkpoint path
- `lease_owner` (optional) — Stable identifier for the claiming agent
- `max_items` (optional) — Number of items to claim. Default: `1`
- `lease_ttl_seconds` (optional) — Lease time-to-live. Default: `300`

Returns: Claimed items with lease metadata.

### get_campaign_item_context

Get full item context plus drafting instructions for a claimed item.

Parameters:

- `checkpoint_path` (required)
- `item_id` (required)

Returns: Control/policy/scope context, current state, and drafting guidance.

### submit_campaign_proposal

Submit an external agent’s proposal without applying it to the platform.

Parameters:

- `checkpoint_path` (required)
- `item_id` (required)
- `proposal` (required) — Campaign proposal payload object

Returns: Proposal acceptance confirmation.

### apply_campaign

Push stored proposals to the platform.

Parameters:

- `checkpoint_path` (required)
- `item_ids` (optional) — Subset of item IDs to apply; omit to apply all

Returns: Apply results with per-item status.

### get_campaign_status

Get structured campaign status with a stable transcript snapshot.

Parameters:

- `checkpoint_path` (required)

Returns: Campaign progress, item states, and transcript.

## Risk Management

Risks are system-scoped (except `list_risk_library`, which is org-level). Mitigation is recorded via `update_risk` — there is no separate `/mitigate` endpoint. Control auto-link on `create`/`seed` is opt-in: it requires `framework_id` plus matching `ControlImplementation` rows on the system.

### list_risks

List risks for a system with optional filters.

Parameters:

- `system_id` (required)
- `category` (optional) — Filter by risk category (`confidentiality`, `integrity`, `availability`, etc.)
- `risk_level` (optional) — Filter by overall risk level (`critical`, `high`, `medium`, `low`)
- `status` (optional) — Filter by lifecycle status

Returns: Risk list with summary metadata.

### get_risk

Get the full risk detail including eager-loaded `artifact_links` (controls, evidence, findings, vendors, monitoring events).

Parameters:

- `system_id` (required)
- `risk_id` (required)

Returns: Full risk record with `artifact_links`.

### create_risk

Create a custom risk for a system. Control auto-link is opt-in: pass `framework_id` plus `suggested_control_families` and the platform will only auto-link controls that already have `ControlImplementation` rows for that framework.

Parameters:

- `system_id` (required)
- `title` (required)
- `category` (required) — `confidentiality`, `integrity`, `availability`, etc.
- `description` (optional)
- `cia_category` (optional)
- `likelihood` (optional)
- `impact` (optional)
- `owner_id` (optional)
- `treatment` (optional) — `mitigate`, `accept`, `transfer`, `avoid`
- `treatment_plan` (optional)
- `treatment_due_date` (optional) — ISO date string
- `review_frequency_days` (optional) — How often the risk should be re-reviewed
- `framework_id` (optional) — Required for control auto-link
- `suggested_control_families` (optional) — List of family short codes (e.g., `["AC", "IA"]`)

Returns: The created risk including `artifact_links`.

### seed_risks

Bulk-instantiate library templates against a system + framework. Each template is scored against the system, and controls are auto-linked per the template’s `suggested_control_families` when matching `ControlImplementation` rows exist.

Parameters:

- `system_id` (required)
- `framework_id` (required)
- `template_ids` (required) — Non-empty list of risk template IDs

Returns: Seed summary with the created risks.

### update_risk

Update risk fields. This is the mitigation surface — set `treatment`, `treatment_plan`, and `treatment_due_date` here rather than via a separate endpoint. Set `status` to a terminal value (e.g., `closed`) to retire a risk; there is no public hard-delete because risks are part of the audit chain.

Parameters:

- `system_id` (required)
- `risk_id` (required)
- `title` (optional)
- `description` (optional)
- `category` (optional)
- `cia_category` (optional)
- `likelihood` (optional)
- `impact` (optional)
- `owner_id` (optional)
- `status` (optional)
- `review_frequency_days` (optional)
- `treatment` (optional) — `mitigate`, `accept`, `transfer`, `avoid`
- `treatment_plan` (optional)
- `treatment_due_date` (optional)

Returns: Updated risk record.

### link_risk_artifact

Attach an artifact (control, evidence, finding, vendor, or monitoring event) to a risk. Pass exactly one artifact reference.

Parameters:

- `system_id` (required)
- `risk_id` (required)
- `link_type` (required) — `contributes_to_risk`, `mitigates_risk`, `evidence_of_risk`
- `control_id` (optional) — Pair with `framework_id`
- `framework_id` (optional) — Required when linking a control
- `evidence_id` (optional)
- `finding_id` (optional)
- `vendor_id` (optional)
- `monitoring_event_id` (optional)

Returns: The created artifact link record.

### unlink_risk_artifact

Remove a previously attached artifact link.

Parameters:

- `system_id` (required)
- `risk_id` (required)
- `link_id` (required)

Returns: Removal confirmation.

### refresh_risk_summary

Re-score the risk using the latest analytics and trigger a best-effort AI summary regeneration. The endpoint always returns 200 with the updated entry. The score commits regardless of AI availability; the AI summary updates only if the AI service is reachable and the org has quota — check whether `ai_summary_generated_at` advanced to confirm AI ran.

Parameters:

- `system_id` (required)
- `risk_id` (required)

Returns: Updated risk entry.

### list_risk_library

Browse the org-level risk template library. Templates expose a `scenario`, `category`, `cia_category`, and `suggested_control_families`.

Parameters:

- `category` (optional) — Filter templates by category

Returns: Library template list.

## Vendor Management

### list_vendors

List all vendor entities in the organization.

Parameters: None

Returns: Vendor list with IDs, names, types, and authorization levels.

### create_vendor

Create a new vendor entity.

Parameters:

- `name` (required)
- `provider_type` (required) — `csp`, `saas`, `managed_service`, `internal`
- `description` (optional)
- `authorization_level` (optional)

Returns: Created vendor record.

### get_vendor

Get vendor details.

Parameters:

- `vendor_id` (required)

Returns: Vendor metadata and linked documents.

### update_vendor

Update vendor fields.

Parameters:

- `vendor_id` (required)
- `name` (optional)
- `description` (optional)
- `provider_type` (optional) — `csp`, `saas`, `managed_service`, `internal`
- `authorization_level` (optional)

Returns: Updated vendor record.

### delete_vendor

Delete a vendor entity.

Parameters:

- `vendor_id` (required)

Returns: Deletion confirmation.

### upload_vendor_document

Upload vendor evidence documents (SOC 2 reports, CRMs, FedRAMP packages).

Parameters:

- `vendor_id` (required)
- `file_path` (required)
- `name` (optional)
- `description` (optional)
- `attestation_type` (optional) — `self_attested`, `third_party_attestation`, `vendor_provided`. Default: `vendor_provided`

Returns: Uploaded document record.

### list_vendor_documents

List documents linked to a vendor.

Parameters:

- `vendor_id` (required)

Returns: Document list with metadata.

### link_evidence_to_vendor

Link an evidence item to a vendor with attestation type. Set `vendor_id` to null to unlink.

Parameters:

- `evidence_id` (required)
- `vendor_id` (optional) — Vendor ID; null to unlink
- `attestation_type` (optional) — `self_attested`, `third_party_attestation`, `vendor_provided`

Returns: Link confirmation.

## Inheritance & Responsibility

### set_control_responsibility

Create or update an inheritance edge for a control.

Parameters:

- `system_id` (required)
- `control_id` (required)
- `framework_id` (required)
- `responsibility_mode` (required) — `inherited` or `shared`
- `source_type` (optional) — `provider`, `internal`, or `hybrid`
- `vendor_id` (optional) — Vendor providing the inherited control

Returns: Created responsibility edge.

### get_control_responsibility

Check if a control is inherited and from where.

Parameters:

- `system_id` (required)
- `control_id` (required)
- `framework_id` (required)

Returns: Responsibility edge details or null.

### remove_control_responsibility

Convert an inherited control back to system-specific.

Parameters:

- `system_id` (required)
- `control_id` (required)
- `framework_id` (required)

Returns: Removal confirmation.

### generate_inheritance_narrative

AI-generate an inheritance narrative grounded in vendor documentation.

Parameters:

- `system_id` (required)
- `control_id` (required)
- `framework_id` (required)

Returns: Draft inheritance narrative text.

### get_stale_edges

Identify controls where the source narrative changed but the inherited control hasn’t been updated.

Parameters:

- `system_id` (required)

Returns: List of stale inheritance edges with source change timestamps.

### sync_stale_edges

Bulk update inherited controls by regenerating narratives from latest source.

Parameters:

- `system_id` (required)

Returns: Sync results with per-control status.

## STIG & CCI

### list_stigs

List STIG benchmarks with optional filters.

Parameters:

- `technology_area` (optional) — Filter by technology area
- `product` (optional) — Filter by product name
- `limit` (optional) — Default: `100`
- `offset` (optional) — Pagination offset. Default: `0`

Returns: STIG benchmark list with IDs, titles, and rule counts.

### get_stig

Get STIG benchmark detail.

Parameters:

- `stig_id` (required)

Returns: Benchmark metadata including title, version, release info, and severity breakdown.

### list_stig_rules

List rules for a STIG benchmark.

Parameters:

- `stig_id` (required)
- `severity` (optional) — Filter by severity (`high`, `medium`, `low`)
- `cci_id` (optional) — Filter by CCI identifier
- `limit` (optional) — Default: `100`
- `offset` (optional) — Pagination offset. Default: `0`

Returns: Rule list with IDs, titles, severities, and linked CCIs.

### get_stig_rule

Get full STIG rule detail.

Parameters:

- `stig_id` (required)
- `rule_id` (required)

Returns: Check text, fix text, discussion, and linked CCIs.

### list_ccis

List CCIs with optional filters.

Parameters:

- `nist_control_id` (optional) — Filter by NIST 800-53 control ID (e.g., `AC-2`)
- `status` (optional)
- `limit` (optional) — Default: `100`
- `offset` (optional) — Pagination offset. Default: `0`

Returns: CCI list with definitions and linked controls.

### get_cci

Get CCI detail with linked SRGs and STIG rules.

Parameters:

- `cci_id` (required) — e.g., `CCI-000015`

Returns: CCI definition, linked SRGs, and linked STIG rules.

### get_cci_chain

Get the full traceability chain: Control -> CCIs -> SRGs -> STIG rules.

Parameters:

- `nist_control_id` (required) — NIST 800-53 control ID (e.g., `AC-2`)

Returns: Complete traceability from control requirements to technical checks.

### get_cci_status

Get CCI-level compliance rollup for a system.

Parameters:

- `system_id` (required)
- `nist_control_id` (optional) — Filter by NIST control ID (e.g., `AC-2`)

Returns: Per-CCI pass/fail status.

### get_cci_implementation

Read a single per-system CCI implementation row by `(system_id, cci_uuid)`. Returns the live impl detail (status, status_source, narrative, ai_generated_narrative, evidence_ids, eMASS fields, has_status_conflict). 404 means the row hasn’t been initialized for this system yet.

Parameters:

- `system_id` (required)
- `cci_uuid` (required) — The CCI catalog UUID (the unique catalog row id, not the `CCI-000XXX` label)

Returns: Full CCI implementation detail.

### get_stig_applicability

Get which STIGs apply to a system based on its profile.

Parameters:

- `system_id` (required)

Returns: List of applicable STIG benchmarks.

### infer_stigs

AI-infer applicable STIGs from the system’s profile.

Parameters:

- `system_id` (required)

Returns: Recommended STIG benchmarks with reasoning.

### get_test_manifest

Fetch the test manifest (applicable STIGs + rules) for a system.

Parameters:

- `system_id` (required)
- `stig_id` (optional) — Scope manifest to a specific STIG benchmark

Returns: Test manifest with applicable rules and scanner assignments.

### submit_test_results

Upload STIG scan results to the platform.

Parameters:

- `system_id` (required)
- `cli_run_id` (required) — CLI scan run identifier
- `results` (required) — Array of test result objects
- `cli_version` (optional) — CLI version string

Returns: Submission confirmation with per-result status.

## Recipes & Workflows

Recipes are markdown playbooks the calling agent reads and executes; workflows describe how to iterate items in a domain and which recipes to pick per item. See RFC 0001 for the contract spec and `docs/src/recipes/` for authoring guides.

### list_recipes

List loaded recipes with their summary metadata (id, name, tier, description, use_when, produces). When `system_id` is supplied, recipes missing required connected sources are hidden by default. Use this to discover which recipes are available, then call `get_recipe(id)` to read the full body.

Parameters:

- `tier` (optional) — Filter to one tier: `official`, `partner`, or `community`
- `produces` (optional) — Filter by what the recipe produces: `evidence`, `narrative`, `both`, or `answers`
- `system_id` (optional) — Filter to recipes runnable against the system’s connected sources
- `include_unavailable` (optional) — Include recipes missing required sources with unavailable reasons. Default: `false`

Returns: Recipe summaries with manifest metadata, required sources, and per-recipe source availability.

### get_recipe

Return one recipe’s full manifest and body. The body is the markdown playbook the calling agent reads to understand the procedure.

Parameters:

- `recipe_id` (required) — Recipe id to fetch

Returns: Recipe manifest plus the markdown body.

### check_sources

Preflight source reachability and candidate recipes for one workflow/control. Use after `start_task` and before opening recipe contexts when the agent needs fresh source/recipe detail.

Parameters:

- `workflow_id` (required) — Workflow id returned by `start_task`
- `control_id` (required)
- `system_id` (optional) — Defaults to active scope
- `framework_id` (optional) — Defaults to active scope

Returns: Capture-plan items with source kind, connected state, candidate recipes, selected recipe, and structured `recipe_gap` entries.

### start_recipe

Open a recipe execution context. Returns a `context_id` the caller passes on subsequent platform-API write tool calls so audit metadata is stamped with `producer_kind='recipe'` automatically. One recipe per session at a time (nesting forbidden in v1). Contexts auto-expire after 1 hour of inactivity.

Parameters:

- `recipe_id` (required) — Recipe id (must be loadable from the registry)
- `recipe_version` (required) — Recipe version the caller intends to run. Cross-checked against the loaded recipe; mismatch is an error.
- `params` (optional) — Inputs the calling agent supplies, validated against the recipe’s params schema
- `selection` (optional) — Structured `RecipeSelection` record from the engagement layer, stored on the context for the eventual `RecipeResult`
- `evidence_ids` (optional) — Evidence ids supplied as inputs for narrative-producing recipes

Returns: Context id and the resolved recipe manifest snapshot.

### end_recipe

Close a recipe execution context and return the `RecipeResult` summary (status, evidence and narrative counts, errors, elapsed time). Must be called once the recipe’s work is complete; failure to call leaves the context in place until the 1-hour expiry sweep.

Parameters:

- `context_id` (required) — Context id returned by `start_recipe`
- `status` (optional) — Caller-supplied disposition: `pass`, `fail`, or `needs_input`. Default: `pass`

Returns: `RecipeResult` summary.

### list_workflows

List loaded workflow playbooks (single-control, scope-question, policy-question, campaign). Each workflow describes how to iterate items in its domain and which recipes to pick per item. Use this before picking a recipe so the agent works at the right granularity.

Parameters:

- `iterates_over` (optional) — Filter to one item-iteration shape: `single_control`, `scope_questions`, `policy_questions`, or `campaign_items`

Returns: Workflow summaries with manifest metadata.

### get_workflow

Return one workflow’s full manifest and body. The body is the markdown playbook the calling agent reads to know how to iterate items and pick recipes per item in this workflow’s domain.

Parameters:

- `workflow_id` (required) — Workflow id to fetch

Returns: Workflow manifest plus the markdown body.