MCP Tool Reference
The MCP server provides 244 static tools. The shipped built-in recipes currently add 25 dynamic per-recipe-script tools (269 in a clean installation); additional loaded recipe scripts can increase the dynamic count.
Cross-Harness Discovery (RFC #113)
Four 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 or when the agent needs to check what Pretorin can do.
check_context
Cheap, unauthenticated probe of session grounding. Reads local CLI config only — no platform calls. Returns:
{
"connected": true,
"platform_api_base_url": "http://localhost:8000/api/v1/public",
"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": {}
}
platform_api_base_url is the non-secret REST endpoint the MCP client will use,
so a local or customer-managed rehearsal can prove it is not pointed at the
hosted production platform. 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": 269,
"tier_counts": {"default": 9, "reference": 164, "workflow": 64, "coordinator": 7, "recipe": 25},
"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. |
coordinator | Normal-profile Campaign lifecycle operation; it does not require a preceding workflow route. |
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).
search_platform_capabilities
Search the product-facing Pretorin Platform Capability Index for features that can satisfy a compliance requirement. This is a searchable product source, not a catalog dump. Agents should call it before creating local tracking documents, spreadsheets, registers, placeholder evidence, or shadow systems of record.
{
"query": "vendor management system for third-party risk and vendor documents",
"framework_id": "soc2",
"control_id": "CC9.2",
"limit": 3
}
Returns compact matches, best-scoring first. The satisfies, mcp_tools, and
search_terms lists below are abridged for readability — the real response
carries every entry the matched capability declares:
{
"source_kind": "pretorin_platform_capabilities",
"query": "vendor management system for third-party risk and vendor documents",
"framework_id": "soc2",
"control_id": "CC9.2",
"total_matches": 3,
"matches": [
{
"capability_id": "vendor_management",
"name": "Vendor Management",
"surface": "Vendors",
"availability": "platform_ui_and_mcp",
"satisfies": ["track third-party providers and service providers"],
"mcp_tools": [
"list_vendors",
"create_vendor",
"upload_vendor_document",
"sign_vendor_residual_acceptance",
"link_evidence_to_vendor"
],
"search_terms": ["vendor", "third-party", "supplier"],
"agent_guidance": "Use Pretorin Vendor Management as the system of record before creating local vendor inventories, assessment trackers, or document folders.",
"source_kind": "pretorin_platform_capabilities",
"system_of_record": true,
"confidence": "high"
}
],
"note": "Search this product capability index before creating local tracking documents, spreadsheets, registers, or placeholder artifacts. A zero-match response means the local catalog did not find a product surface; it is not proof that Pretorin lacks one."
}
Capabilities are curated per product surface, so a vendor query also returns
neighboring surfaces — here vendor_assessment_workflows (assessment
templates, launches, scoring, and reviewer finalization) ranks second. Read the
capability_id and surface of each match rather than assuming the first one
owns every tool in the domain. A zero-match response is not proof that Pretorin
lacks the surface; ask the user or check the platform.
Availability values:
| Availability | Meaning |
|---|---|
platform_ui_and_mcp | Pretorin has a product surface and MCP tools the agent can use. |
platform_ui_with_mcp_read | Pretorin has a product surface plus read-oriented MCP context, but the full workflow may stay in the platform UI. |
platform_ui_only | Pretorin has a product surface, but the current MCP/CLI does not expose the workflow. |
Parameters:
query(required) — Plain-English requirement or proposed local artifact.framework_id(optional) — Framework context.control_id(optional) — Control context.limit(optional, 1–10, default 5) — Maximum matches to return.
When to call: Before creating local artifacts to satisfy a requirement that sounds like vendor management, risk tracking, POA&M/weakness tracking, vendor assessments, formal assessments, policy management, system scope/profile management, approval workflow, compliance report generation, eMASS synchronization, SPRS scoring, OSCAL packages, STIG/CCI tracking, or another GRC platform feature.
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.
Large playbooks can be read without host-side clipping. Pass mode="compact"
to keep the complete Markdown body and every validation keyword while omitting
non-validating schema and tool-description annotations. Pass
section="<heading-id>" to retrieve
one complete heading and its nested content; the response lists valid heading
IDs in response_metadata.available_sections. Selection is explicit and
response_metadata.truncated remains false for a complete requested slice.
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, issues, control status, monitoring events) share one audit-trail flag and one plan-attribution pair.
allow_unverified_sources(optional, defaultfalse) — Permit a write when source attestation shows a mismatch. Listed below as “(audit-trail flag)”. Set it only when the calling agent has a deliberate reason to bypass that guardrail.plan_id(optional) — Id of the agent-authored Plan this write belongs to. When supplied, the platform write is tagged with the Plan and the Plan’s localproduced_artifacts[]audit chain gets an entry.step_index(optional) — Zero-based index of the Plan step that triggered the write. Only meaningful alongsideplan_id.
There is no scope-override parameter. An MCP agent can never write outside the active system/framework context by passing a flag: only a human switching context with pretorin context set moves that boundary. A cross-scope write is refused regardless of the arguments sent.
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 after check_context whenever the user references compliance work (a control, system, framework, questionnaire, source preflight, 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.
When the top-level entities.intent_verb is campaign, routing is intentionally
route-only: the response selects Campaign guidance and points to
check_campaign_runtime, but creates no generic Plan. That inspection points
to preview_campaign only when launch_ready=true; the Campaign coordinator
then owns the parent/child hierarchy. This exception does not apply to an
assigned child call carrying trusted parent_plan_id and campaign_context;
that path adopts the deterministic child draft as described below.
The one exception is pure reference questions (“show me AC-2”, “list frameworks”) — those go directly to the read-side tools without start_task.
Argument shape: all prompt-derived fields (intent_verb, raw_prompt, system_id, framework_id, control_ids, scope_question_ids, policy_question_ids) must be nested inside the entities object. Only active_system_id, active_framework_id, skip_inspect, create_new_plan, and the runtime-owned Campaign fields parent_plan_id plus campaign_context live at the top level. Flattening prompt entities to the top level is a common caller bug: such top-level copies are ignored by the handler (not read, not rejected), so the route is decided from entities alone and the misplaced fields silently have no effect.
Parameters:
entities(required) — Structured entities extracted from the user prompt. Required sub-fields:intent_verb(one ofwork_on,collect_evidence,draft_narrative,answer,policy_definition,scope_artifacts,preflight,stig_scan,risk_assessment,formal_assessment,campaign,inspect_status) andraw_prompt(original verbatim text). Optional sub-fields:system_id,framework_id,control_ids,scope_question_ids,policy_question_ids. All prompt-derived entities live here — do not flatten them to the top level.preflightroutes source discovery, binding, verification, and recipe provisioning to thepreflightworkflow. The three lifecycle intents route tostig-scan-remediation,risk-assessment, andformal-assessment, respectively.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 byinspect_statuswhen 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:falseinclude_source_hints(optional) — Return fullsource_hintsinsuggested_capture_planinstead of compact hint summaries. Only honored for single-control tasks; multi-control summaries never inline hints. Default:falsecreate_new_plan(optional) — Force a separate Plan even when an exact-context non-terminal Plan already exists. Default:falseparent_plan_id(Campaign child only) — Trusted parent Campaign Plan ID injected by the runtime. It must be supplied together withcampaign_context; never derive it from prompt text.campaign_context(Campaign child only) — Frozen Campaign type/domain, item ID, attempt, exact objective UUID roster, expected outputs, process criteria, and publication/review policy.campaign_item_idis required. Campaign retries cannot passcreate_new_plan=true; they deterministically resume the assigned child Plan.
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. For a single control, the local draft Plan already contains the required evidence-expectation-mapping anchor. The calling agent authors concrete discovery and capture steps before that anchor and activates the Plan; mapping then completes before assessment or narrative composition. A Campaign child also preserves each coordinator-owned process anchor exactly once and in order while authoring its own bounded steps between them. The capture plan carries compact per-expectation items: verbose source_hints are replaced with source_hint_count and preferred_source_hint; pass include_source_hints=true for full hints. For multiple controls (e.g. a control family routed to the campaign workflow), the plan is a bounded per-control summary with no items or recipe_gaps keys — counts, statuses, and a top_capture_hint per control — sized for agent context budgets. Call check_sources for the full per-expectation detail of any one control.
Plan reuse: before creating an ordinary Plan, start_task looks for
non-terminal Plans in the identical execution context—same workflow, scope,
intent verb, and prompt text ignoring case and whitespace. Matching standalone
Plans come back in resume_candidates; a single candidate is adopted
automatically. A top-level Campaign intent skips this creation/reuse path. For
a Campaign child, the coordinator has already created or strictly reconciled
the deterministic assigned Plan; start_task adopts that exact Plan rather
than creating one or adopting an unrelated interactive Plan. Candidates never
cross a system/framework or parent/item boundary.
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 likeaccess-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.
OSCAL Artifacts
Read-only access to validated OSCAL export artifacts (SSP/SAR/SAP/POA&M/ component-definition). Generation stays on the platform; these tools list and inspect what exists. Both are read-only and not active-context-enforced.
list_oscal_artifacts
List validated OSCAL artifacts for a system. Server-filtered to
generation_state = succeeded AND validation_status = valid.
Parameters:
system_id(required)artifact_type(optional) —ssp,sap,sar,poam,component_definition,bundleframework_id(optional)assessment_id(optional)limit(optional, 1–100, default 50)offset(optional, default 0)
Returns: artifacts (list of summaries with type, version, oscal_version, validation status) and total.
get_oscal_artifact
Get artifact metadata including the two-tier validation report and a presigned download URL.
Parameters:
system_id(required)artifact_id(required)
Returns: Full metadata — oscal_version, generator_version, validation_report, checksum_sha256, file_size, and download_url.
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 the local cache and re-resolve the latest version from the channel this install actually upgrades through (PyPI for Python-package installs; the public tap’s releases for raw binaries; the published tap formula for Homebrew installs). Default:false
Returns: Current version, latest version, update available flag, passive-notification and check state, plus four upgrade_* fields:
upgrade_command— the command (or, where no self-update exists, the openable release URL) for this install. Never a pip/uv hint for a frozen binary.upgrade_requires_human_approval—truewheneverupgrade_commandis a command that mutates this machine’s Pretorin install. Present it to the human operator; do not execute it.falseonly for installs with no self-update path, where the value is a download page and nothing changes until a person acts on it.upgrade_restart_required—trueon the same routes: an already-running MCP server keeps serving the previous version until the host restarts it.upgrade_note— prose explaining, for this specific install, what the command changes and why a restart is needed. Route-specific, so it can never disagree with the command beside it.
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 nameframework_id(optional) — Defaults to active context
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.
get_preflight
Read the local preflight verdict for the active (or given) scope: which recommended source kinds are mapped to host-local resolvers and their per-kind rollup (ready/degraded/missing/unverified/unmapped). This is the CLI-local source of truth for source availability — the platform cannot verify connections. When authenticated it also seeds the platform’s in-scope recommended source kinds into the artifact (persisted only when the profile changed something; offline it is a pure local read).
Parameters:
system_id(optional) — System ID or name; defaults to the active scopeframework_id(optional) — Framework ID; defaults to the active scopesource_kind(optional) — Canonical source kind. When omitted, returns a bounded summary carrying every kind’s verdict and action. When supplied, returns that one kind’s full resolver, scope, identity, capability, and verification detail.
Returns: Preflight artifact with per-kind resolver bindings and rollup. Returns exists=false with a hint when no artifact has been built yet and the platform recommends nothing.
verify_preflight
Probe every resolver bound in the preflight artifact for this scope, persist the results, and return the refreshed verdict. Probes run locally on the CLI host (e.g. gh auth status, az account show, workspace path checks).
Parameters:
system_id(optional) — System ID or name; defaults to the active scopeframework_id(optional) — Framework ID; defaults to the active scopesource_kind(optional) — Canonical source kind. When supplied, probe and return only that kind’s resolvers; this partial verification does not refresh the artifact’s profile-widelast_verified_attimestamp.
Returns: Refreshed preflight verdict with per-resolver probe results.
update_preflight
Bind resolver collections to recommended source kinds and persist the preflight artifact. Each kind maps to a collection of resolvers (each tells a distinct piece of the evidence story); a kind’s collection is replaced wholesale. Resolver types are open: workspace_path, cli_tool, command, manual/attested, mcp, connected_api, pretorin_feature, or any custom type with a probe.
Parameters:
bindings(required) — Array of per-kind resolver bindings to upsert. Each entry haskind(canonical source kind), optionalrecommendedflag, and aresolversarray (each resolver hastype, optionalname,constraints,scope,params, andcapabilities).system_id(optional) — System ID or name; defaults to the active scopeframework_id(optional) — Framework ID; defaults to the active scopesource_kind(optional) — Canonical source kind to return with full detail after the update. This filters the response only, never which bindings are written.
Returns: The persisted preflight artifact with the updated bindings.
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.
set_target_scale_tier
Declare or clear the engagement’s target scale tier for a system/framework scope. The declared tier overrides the platform-derived tier used for guidance and expectation coverage.
Parameters:
system_id(optional) — Defaults to the active scopeframework_id(optional) — Defaults to the active scopetarget_scale_tier(required) —baseline,moderate, orcomprehensive; passnullto clear the override
Returns: target_scale_tier, derived_scale_tier, effective_scale_tier, and the platform’s reasoning.
Evidence Management
search_evidence
Search evidence within exactly one active system/framework scope. With query, performs RAG semantic search over attached evidence and scoped unattached evidence (including org policy documents) so agents can reuse existing evidence before creating new artifacts. Without query, lists evidence linked to control_id or the current framework scope.
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 controlframework_id(optional) — Filter by frameworkquery(optional) — Natural-language RAG query. Provide this before creating evidence to find currently attached evidence and reusable unattached evidence.include_attached(optional) — Whenqueryis set, include evidence already attached tocontrol_id. Default:trueinclude_unattached(optional) — Whenqueryis set, include scoped evidence not attached tocontrol_id, including org policy evidence. Default:truemin_similarity(optional) — Whenqueryis set, minimum semantic similarity threshold. Default:0.6limit(optional) — Maximum number of results (default 20 for listing; RAG queries default to 5 and are capped at 50)include_metadata/include_full_detail(optional) — Whenqueryis set, request full per-result metadata and control mappings. Default:false, which returns compact count markers such asmetadata_key_countandcontrol_mapping_count.snippet_only(optional) — Whenqueryis set, replace large body fields such asartifact_contentandmatched_textwith short snippets. Default:truemax_body_chars(optional) — Whenqueryis set andsnippet_only=false, maximum characters to keep per body field. Use a positive value to opt into capped body content. Default:0snippet_chars(optional) — Whenqueryis set, maximum characters returned for each body-field snippet. Default:500
Returns: Matching evidence items. RAG query responses are compact by default: full metadata and control mappings are replaced with counts, and full body fields are replaced with snippets and omitted-character counts so hot-path agent calls stay below tool-result limits. Pass include_metadata=true only when full per-result detail is needed; pass snippet_only=false with a positive max_body_chars only when body content is explicitly needed.
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 demonstratesartifact_content(required) — Markdown body containing the actual evidence artifact. Start directly with factual content; omit section headers and standalone bold labels because the SSP supplies headings. Do not include gap lists, missing-information placeholders, unresolved caveats, or remediation backlog.evidence_type(required) — Must be one of the canonical evidence typessystem_id(optional) — Defaults to active scopecontrol_id(optional)framework_id(optional)dedupe(optional) — Default:truecode_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 excerptcode_repository(optional) — Git repository URLcode_commit_hash(optional) — Git commit hashsource_uri,source_label,source_locator,source_excerpt,capture_method(optional at the MCP layer) — Structured provenance inputs. If omitted, the handler derives safe defaults from code context or active scope. Note: the platform’s audit-metadata contract (issue #701) requiressource_locatorfor agent-produced evidence — the handler auto-deriveslines N-Mfromcode_line_numberswhen present, but for non-code sources (policy excerpts, docs, vendor reports, dashboards) you must pass an explicit locator such assection 3.7orpage 4 paragraph 2, otherwise the platform rejects the write withMissing: source_locator.recipe_context_id(required) — Active recipe execution context fromstart_recipe; evidence is stampedproducer_kind='recipe'automatically.allow_unverified_sources(optional, audit-trail flag)plan_id,step_index(optional) — Plan attribution; see Common Write-Side Parameters
Returns:
evidence_idcreated— true if new, false if reusedlinked— whether control/system link succeededmatch_basis—exact_name_desc_type_control_frameworkornone
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); optionalrelevance_notes,code_file_path,code_line_numbers,code_snippet,code_repository,code_commit_hash,source_uri,source_label,source_locator,source_excerpt,capture_method. Artifact content uses the same no-heading, no-gap-discussion rule ascreate_evidence. The platform’s audit-metadata contract (issue #701) requiressource_locatorfor agent writes — pass an explicit locator (e.g.,section 3.7,lines 84-88,page 4 paragraph 2) on each item from a non-code source, or the platform will reject the corresponding item withMissing: source_locator.system_id(optional) — Defaults to active scopeframework_id(optional) — Defaults to active scoperecipe_context_id(required) — Active recipe execution context fromstart_recipe; every item in the batch is stampedproducer_kind='recipe'. All items share the same context — per-item context variation is not supported in v1.allow_unverified_sources(optional, audit-trail flag)plan_id,step_index(optional) — Plan attribution; see Common Write-Side Parameters
Returns: Batch creation summary with per-item results and created evidence IDs.
link_evidence
Link an existing evidence item to a control and classify its relationship to the control’s declared evidence expectations. Narrative citations ground claims but do not satisfy expectation coverage.
Parameters:
evidence_id(required)control_id(required)system_id(optional) — Defaults to active scopeframework_id(optional)expectation_key(preferred) — Stable key fromget_control_context.expectation_coverageexpectation_item(optional) — Raw expectation text; the platform hashes it to the stable key. Use this orexpectation_key.unbound_reason(conditional) — Required instead of an expectation binding when the artifact supports no declared expectation. The platform preserves the control link, clears any expectation binding the artifact currently has, and records the reason in its audit chain; the call fails closed unless the platform confirms the unbind. Never use it on an artifact that is correctly bound — it removes real expectation coverage. Mutually exclusive with the expectation fields.allow_unverified_sources(optional, audit-trail flag)plan_id,step_index(optional) — Plan attribution; see Common Write-Side Parameters
Pass an expectation binding or unbound_reason; an unclassified MCP agent
link is refused. When the write carries plan_id and the mapping step’s
step_index, the Plan records the evidence id and expectation key (or unbound
reason) under produced_artifacts.
Returns: Link confirmation plus expectation_mapping.status (bound or intentionally_unbound).
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 scopeframework_id(optional) — Defaults to the active scope and must match itoverride_system_mismatch(optional, defaultfalse) — Permit cross-system attachmentoverride_reason(optional) — Required whenoverride_system_mismatchis trueplan_id,step_index(optional) — Plan attribution; see Common Write-Side Parameters
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 UUIDsystem_id(optional) — Defaults to active scopeframework_id(optional) — Defaults to the active scope and must match itoverride_system_mismatch(optional, defaultfalse)override_reason(optional) — Required whenoverride_system_mismatchis trueplan_id,step_index(optional) — Plan attribution; see Common Write-Side Parameters
Returns: Link confirmation with link_summary.stig_rule_workflow_id.
link_evidence_to_objective_implementation
Link an existing evidence item to a per-system assessment objective implementation row (CMMC / NIST 800-171A). Use when you already have the objective implementation UUID (from list_objectives or get_objective_implementation). The platform also mirrors the evidence into the parent control’s library, so a separate link_evidence call for the same artifact is redundant.
Parameters:
evidence_id(required)assessment_objective_implementation_id(required) — The per-system objective implementation row UUID, not the3.1.1.alabelsystem_id(optional) — Defaults to active scopeframework_id(optional) — Defaults to and must match the active scopeplan_id,step_index(optional) — Plan attribution; see Common Write-Side Parameters
This is a governed write: it must match the active MCP system/framework context, and agents cannot override that boundary (there is no override_system_mismatch escape here).
Returns: Link confirmation for the objective implementation row.
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 uploadname(required) — Evidence namesystem_id(optional) — Defaults to active scopeevidence_type(optional) — Default:otherdescription(optional) — Evidence descriptioncontrol_id(optional)framework_id(optional)allow_unverified_sources(optional, audit-trail flag)plan_id,step_index(optional) — Plan attribution; see Common Write-Side Parameters
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 deletesystem_id(optional) — Defaults to active scopeframework_id(optional) — Defaults to active scopeplan_id,step_index(optional) — Plan attribution; see Common Write-Side Parameters
Returns: Deletion confirmation.
get_evidence_attestation
Fetch the DSSE attestation envelope (ADR 0003) for an evidence record. Returns the in-toto Statement, signing key fingerprint, and provenance metadata. Read-only; no recipe context required.
Parameters:
evidence_id(required) — The evidence item ID to fetch the attestation forinclude_lineage(optional, defaultfalse) — Also return the full lineage of attestations for this evidence (newest first)include_archived(optional, defaultfalse) — Wheninclude_lineageis set, include archived attestations
Returns: DSSE envelope plus statement, signer fingerprint, and provenance fields. With include_lineage=true, also includes prior envelopes. Returns a structured attestation_unavailable error when the platform attestation surface is disabled or no envelope exists for the row.
get_narrative
Get the current narrative record for a control.
Parameters:
control_id(required)system_id(optional) — Defaults to active scopeframework_id(optional) — Defaults to active scopeallow_unverified_sources(optional, audit-trail flag)
Returns: Narrative text, status, AI confidence metadata, and citations[]. Each citation includes grounding (claim_grounded, document_grounded, or ungrounded) plus any locator_chunk_index and matched_excerpt.
Implementation Context
get_control_context
Get rich context for a control including AI guidance, statement, objectives, scope status, current implementation details, and the full per-expectation coverage map.
This is the read that gives an author both halves of the grading contract in one call: ai_guidance is the rubric the platform’s AI review scores against, and ai_analysis is its last verdict against that rubric.
Parameters:
control_id(required)system_id(optional) — Defaults to active scopeframework_id(optional) — Defaults to active scope
Returns: Combined control metadata and implementation details. expectation_coverage maps each expectation to its expectation_key, item, tier, covered state, bound evidence, and unconfirmed suggestions. evidence_expectations carries one tier per expectation (top-level, and mirrored under ai_guidance), and scale_tier.tier is the confirmed target tier to compare them against. ai_analysis is the read-only projection of the platform’s last AI review — see Reading the AI review. Null on platforms that predate the field.
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}objectsplan_id,step_index(optional) — Plan attribution; see Common Write-Side Parameters
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. For a large
questionnaire, set include_guidance=false to omit static template and
question guidance from the MCP projection.
Parameters:
policy_id(required)include_guidance(optional, defaulttrue)
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}objectsplan_id,step_index(optional) — Plan attribution; see Common Write-Side Parameters
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 scopeframework_id(optional) — Defaults to active scopeallow_unverified_sources(optional, audit-trail flag)
Returns: Current status, narrative, evidence count, operating_evidence_count (excluding the automatic scope document), compact expectation_coverage, and issue metadata.
get_control_issues
Get issues for a control implementation.
Parameters:
control_id(required)system_id(optional) — Defaults to active scopeframework_id(optional)status(optional) —all(default),open, orresolvedlimit(optional) — 1–1000, default 50offset(optional) — Default 0snippet_only(optional) — Replace body-sized fields such ascontentwith bounded snippets; defaulttruemax_body_chars(optional) — Withsnippet_only=false, retain at most this many characters per body field; use a positive value to request body content
Returns: A bounded Issue page. total, open_total, blocking_total, and non_blocking_total describe the returned page; matched_total, matched_open_total, matched_blocking_total, and matched_non_blocking_total describe the complete filtered set before pagination. returned, limit, offset, and has_more make pagination explicit. An unreadable_total appears only if the platform returned a record that is not an issue object, so nothing vanishes silently.
Open Issues are serialized before resolved history (with stable relative order inside each group), including when status=all. This ensures a bounded page or final response-guard compaction retains approval-gating work first. For full content, request a small page with snippet_only=false and a positive max_body_chars.
Demonstrated control deficiencies gate approval. Calibrated evidence-gap Issues carry is_blocking: false and are tracked without gating approval; non_blocking_total reports them. Above-target “areas to strengthen” are still reported in ai_analysis.gaps_detail, where is_blocking can be false, and are never filed as Issues.
Issues filed by the AI review also carry ai_review_finding_key, which matches a finding_key in ai_analysis.gaps_detail or .unsupported_claims — that is how you trace an issue back to the reasoning behind it. Treat ai_analysis as explanatory read-only output: the platform reconciler owns AI finding Issues, so agents must not copy those findings into add_control_issue. Agent-authored Issues are only for gaps independently observed in the workspace or another connected source. This avoids duplicate Issues even when an analysis is stale or superseded.
Each row also carries control_implementation_id and issue_id — the pair the Issue treatment tools are addressed by — plus lifecycle_status and gate_status.
get_system_issues
List issues across a whole system/framework instead of one control at a time. Use this to find open remediation work without walking every control.
Parameters:
system_id(optional) — Defaults to active scopeframework_id(optional) — Defaults to active scopestatus(optional) —open(default),resolved, orallsource(optional) —manual,rfi,monitoring,cli,mapping,finding,ai_review, orallcontrol_id(optional) — Narrow to a single controllimit(optional) — 1–1000, default 500offset(optional) — Default 0
Returns: The same normalized shape and counts as get_control_issues (total, open_total, blocking_total, non_blocking_total, and unreadable_total when applicable), scoped to the returned page. Adds matched_total — every row the filter matched server-side, which exceeds the page counts when paginating — plus limit, offset, and the resolved system_id and framework_id. Rows add control_id, control_title, and control_status.
get_control_notes
Deprecated alias for get_control_issues.
Parameters:
control_id(required)system_id(optional) — Defaults to active scopeframework_id(optional)status,limit,offset,snippet_only,max_body_chars(optional) — Same bounded-read controls asget_control_issues
Returns: The same bounded Issue page as get_control_issues. Compatibility responses also include notes.
Reading the AI review
The platform reviews a control narrative against ai_guidance.evidence_expectations and persists the verdict. get_control_context and get_control_implementation return it as ai_analysis:
gaps_detail[]— each{text, tier, tier_label, exceeds_target, is_blocking, finding_key}.is_blocking: falsemeans the gap sits above your target scale tier: worth doing, not required.unsupported_claims[]— each{claim, reason, finding_key}: a narrative claim no cited evidence backs.strengths[],recommendations[],confidence_score.
confidence_score is null until a review has scored the narrative, so it — not the presence of ai_analysis — tells you whether a review has run.
issues[].is_blocking remains the authority on what gates approval. ai_analysis explains the review’s reasoning; the issue list records what the platform actually enforced, including any human judgement layered on top.
update_narrative
Push a narrative text update produced by a narrative recipe.
Parameters:
control_id(required)narrative(required) — Agent-authored control narrative: no section headers, standalone bold labels, or images; target 150–300 words, require at least 800 characters, and never exceed 400 words; start directly with a short implementation overview, include anExpectation | Implemented behavior | Evidencetable, and add supported operating detail. A few bullets alone are insufficient. Do not pad, restate the control, or include gap lists, missing-information placeholders, unresolved caveats, or remediation backlog; useadd_control_issue.system_id(optional) — Defaults to active scopeframework_id(optional) — Defaults to active scopeis_ai_generated(optional) — Default:falserecipe_context_id(required) — Active narrative-producing recipe context fromstart_recipeevidence_ids(required) — Evidence ids cited by the narrative. Normally non-empty; pass an explicit empty array only inneeds_input_onlymode.needs_input_only(optional) — Default:false. Narrow, server-authorized Campaign-only evidence-free mode:narrativeis omitted andevidence_idsis empty. Allowed only for a current initial/interim child after the shared frozen preflight recorded limitations and every objective was recorded asneeds_input. Interactive callers never set it, which is whynarrativesits outside the schema’s top-levelrequiredlist.evidence_citations(optional) — Full citation objects withevidence_id, optionalcitation_role,locator_chunk_index, andmatched_excerpt. Mapsearch_evidence’schunk_indexandmatched_textto the locator fields for claim-level grounding.trigger_review(optional) — Default:false. Explicit exception that asks the platform to review this final narrative generation.wait_for_review(optional) — Withtrigger_review=true, wait for exact-generation analysis before returning. Defaults totruefor interactive calls. Campaign workers must setfalse; the returned review job ID and target generation are persisted independently from child execution.review_requested_by_user(conditional) — Must betruewithtrigger_review=true, confirming the user explicitly requested review. Without it, the tool refuses before saving or enqueueing review.allow_unverified_sources(optional, audit-trail flag)plan_id,step_index(optional) — Plan attribution; see Common Write-Side Parameters
Returns: Update confirmation. A normal Plan-attributed single-control save
also returns its verified mapping_gate and the structured
expectation_coverage read-back used to gate composition.
For a Plan-attributed single-control write, complete the required
evidence-expectation-mapping step first: bind or explicitly classify every
artifact, re-read get_control_context, and complete the step with its typed
evidence_mapping result. The canonical loop is: search/reuse evidence →
create evidence as needed → bind expectation keys → re-read coverage → save the
mapped, cited narrative with review disabled. The normal result includes
mapping_gate and expectation_coverage (covered, uncovered, and
unbound_evidence_count) for the handoff. Only an explicit user request may
set both review flags; that review result additionally includes an optional
coverage_warning and analysis only after the reviewed generation matches the
requested target generation. A Campaign uses the non-blocking form, records the
returned job/generation pair on its child Plan, and lets the platform review
advance independently.
The single-control workflow also seeds narrative_min_chars: 800; call
complete_plan after the attributed steps and revise with supported detail if
that bounded completion gate fails.
add_control_issue
Admit one independently supported control gap as a canonical Issue. This is not
a general task writer: optional advice, missing context, source/recipe gaps,
evidence suggestions, subtasks, and findings already represented by an Issue do
not qualify. Open issue-create with one stable expectation key, the exact
unmet expectation, observed gap and independent observation basis, risk basis
and ratings, clearance condition, and non-empty minimum-evidence list. Read
current Issues before writing. One expectation gets one Issue.
Parameters:
control_id(required)content(required) — Exactly the admittedobserved_gap, as one plain sentence of at most 20 wordstitle(required) — Stable title beginning with the admittedexpectation_keyinherent_likelihood,inherent_impact(required) — NIST 800-30 ratings fromvery_lowthroughvery_highrisk_basis(required) — Rationale for the initial provisional risk evaluationdetected_at,idempotency_key(optional) — Detection timestamp and organization-scoped retry keyissue_kind(optional) —control_gap(default) orevidence_gap. Useevidence_gaponly for a completed search that did not observe required active-tier evidenceis_blocking(optional) — Defaulttrue. Evidence-gap Issues must setfalse; demonstrated control deficiencies staytruesearch_context(conditional) — Search scope, query, and result provenance for anevidence_gapIssuerecipe_context_id(required) — Active candidate-specificissue-createcontext fromstart_recipesystem_id(optional) — Defaults to active scopeframework_id(optional) — Defaults to active scopeallow_unverified_sources(optional, audit-trail flag)plan_id,step_index(optional) — Plan attribution; see Common Write-Side Parameters
Returns: The created Issue record. The recipe then creates one minimal draft
treatment plan on that same Issue, preserving the clearance condition and
minimum evidence. One issue-create context can create at most one Issue.
Canonical Issue Treatment Tools
All treatment tools take control_implementation_id and issue_id, returned by add_control_issue or get_control_issues. Plan/action tools additionally take the relevant plan_id and action_id.
| Tool | Purpose |
|---|---|
get_issue_risk_history | Read immutable risk-evaluation versions |
add_issue_risk_evaluation | Append a provisional evaluation; confirm it with confirm_issue_risk_evaluation |
set_issue_poam_metadata | Replace Issue-owned POA&M projection facts |
get_issue_acceptance_history | Read formal risk-acceptance decisions |
get_issue_plans | Read versioned treatment plans |
get_issue_plan | Read one plan version with its full approval lifecycle |
create_issue_plan, update_issue_plan, submit_issue_plan | Build a draft and submit it for approval review |
confirm_issue_risk_evaluation | Confirm the risk determination (supersedes active acceptances) |
accept_issue_risk, revoke_issue_risk_acceptance | Record or withdraw a formal risk acceptance |
approve_issue_plan, reject_issue_plan | Decide a submitted plan |
review_issue_opa | Review an approved CMMC Operational Plan of Action |
complete_issue_plan | Complete an approved plan — Issue becomes verification_pending, not closed |
verify_issue | Verify treatment and close the Issue (the only closure path) |
void_issue | Retire an invalid finding — terminal and irreversible; requires explicit force=true confirmation |
get_issue_actions | Read ordered plan actions and milestones |
get_issue_action | Read one action or milestone |
create_issue_action, update_issue_action, delete_issue_action | Manage work while a plan remains draft |
transition_issue_action | Execute work in an approved plan (blocked/cancelled require a note) |
create_issue_plan / update_issue_plan take kind of remediation or cmmc_opa. The CMMC OPA fields (opa_eligibility_basis, review_frequency_days, next_review_at) are valid only on a cmmc_opa plan, and the two review fields must be supplied together.
set_issue_poam_metadata is a full replacement: every field the platform accepts is written on each call, so an omitted field is cleared.
A WRITE or ADMIN API token is a first-class governed actor for the whole lifecycle, including risk confirmation, acceptance and revocation, plan approval/rejection/review/completion, verification, and voiding. The platform enforces every precondition and returns an explanatory conflict when one is unmet. Two determinations remain interactive-only: poam-set --false-positive and --operational-requirement are rejected for API tokens.
add_control_note
Deprecated alias for add_control_issue. It does not take the canonical
risk fields: title, inherent_likelihood, inherent_impact, risk_basis,
issue_kind, is_blocking, search_context, detected_at,
idempotency_key, and Plan attribution are all rejected.
Parameters:
control_id(required)content(required)recipe_context_id(required) — Only a legacycontrol-note-attestationcontext is accepted; anissue-createcontext is refused with a pointer toadd_control_issuesystem_id,framework_id(optional) — Default to the active scopeallow_unverified_sources(optional, audit-trail flag)
resolve_control_issue
Reopen or update metadata on one existing Issue while evaluating it through
issue-evaluate. Generic update cannot close an Issue. Governed closure is
verify_issue after treatment reaches verification_pending; a duplicate or
finding that was never valid uses the explicit, irreversible void_issue
decision.
Parameters:
control_id(required)issue_id(required)recipe_context_id(required) — Activeissue-evaluatecontext for this one Issuesystem_id(optional) — Defaults to active scopeframework_id(optional) — Defaults to active scopeis_resolved(optional) —falsereopens;trueis rejected because closure is governedresolution_note(optional) — Closure-justification metadata only; it does not close the Issuecontent(optional) — Updated issue contentis_pinned(optional)allow_unverified_sources(optional, audit-trail flag)plan_id,step_index(optional) — Plan attribution; see Common Write-Side Parameters
Returns: The updated Issue record. issue-evaluate itself finishes with one
bounded disposition: verified, one next action, time-bounded risk acceptance,
an explicit void candidate, or already terminal. It recognizes an active
acceptance before requiring a plan. Every nonterminal source-owned
RFI/finding/AI-review Issue stays on its exact source workflow; after source
reconciliation moves it to verification_pending, it is verified against the
current source result and supporting evidence without a retroactive plan. A
planless non-source Issue must be reopened before treatment can be added. It
never creates child Issues.
resolve_control_note
Deprecated alias for resolve_control_issue. Accepts note_id instead of
issue_id and takes no Plan attribution (plan_id/step_index); otherwise the
parameter set matches (control_id, recipe_context_id, content,
is_resolved, is_pinned, resolution_note, system_id, framework_id,
allow_unverified_sources).
Assessment Objectives
Assessment objectives are the assessable leaves under a CMMC / NIST 800-171A control — the rows a C3PAO actually adjudicates. They are per-system implementation rows with their own status, narrative, and evidence links.
Two things the tool list alone gets wrong:
- Objective UUIDs are not objective labels. Every tool here takes the implementation row UUID (from
list_objectivesorget_control_context), never the3.1.1.adisplay label. - Approving an objective never approves its parent control. Objectives are leaves; issues live at the control level, and final control approval is a human decision in the UI.
list_objectives
List per-system assessment objective implementation rows. Filter by framework_id + control_id for one control’s objectives, or by status. Each row carries effective status, status_source, narrative, evidence_ids, and has_status_conflict. control_id is normalized server-side (CMMC / 800-171 IDs keep their native shape).
Parameters:
system_id(optional) — Defaults to active scopeframework_id(optional) — Filter to one framework, e.g.cmmc_level_2ornist-800-171control_id(optional) — Canonical control ID fromlist_controls(e.g.AC.L2-3.1.1,03.01.01)status(optional) — Filter by effective objective statusonly_conflicts(optional, defaultfalse) — Only rows wherehuman_statusdisagrees withscan_statuslimit(optional, default100),offset(optional, default0)
Returns: Objective implementation rows.
get_objective_implementation
Read a single objective implementation row by (system_id, objective_uuid). Returns full detail: objective_id, objective_text, status, status_source, narrative, ai_generated_narrative, evidence_ids, has_status_conflict, and approved_by/approved_at. A 404 means the row has not been seeded yet for this system.
Parameters:
system_id(required)objective_uuid(required) — The objective implementation row UUID
Returns: Full objective implementation detail.
update_objective_implementation
Commit agent-authored working fields for one objective before approval. Ordinary updates may only set status=in_progress; the explicit completion decision goes through approve_objective_implementation.
Parameters:
system_id(required)objective_uuid(required)status(optional) — Onlyin_progressis accepted herenarrative(optional)evidence_ids(optional) — Array of evidence IDsreason(optional, max 500 chars)
Returns: The updated objective implementation row.
approve_objective_implementation
Explicitly and idempotently approve one objective implementation. The objective must already be past not_started with a substantive committed narrative and approval-supporting scoped evidence; otherwise the server returns 409 listing the missing prerequisites. Approval is stamped with agent source and promotes the AI draft to the committed narrative. Issue-blind by design: it never consults control issues.
Parameters:
system_id(required)objective_uuid(required)
Returns: The approved objective implementation row.
Compliance Updates
update_control_status
Start or reopen authoring for a control.
Parameters:
control_id(required)status(required) —in_progresssystem_id(optional) — Defaults to active scopeframework_id(optional)allow_unverified_sources(optional, audit-trail flag)plan_id,step_index(optional) — Plan attribution; see Common Write-Side Parameters
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 scopeframework_id(optional) — Defaults to active scopeseverity(optional) —critical,high,medium,low,info. Default:mediumevent_type(optional) —security_scan,configuration_change,access_review,compliance_check. Default:security_scancontrol_id(optional)description(optional)allow_unverified_sources(optional, audit-trail flag)plan_id,step_index(optional) — Plan attribution; see Common Write-Side Parameters
Returns: The created monitoring event.
generate_control_artifacts
Generate read-only AI drafts for a control narrative, evidence recommendations, and recommended issues.
Parameters:
system_id(required)control_id(required)framework_id(required)working_directory(optional) — Local workspace path for code-aware draftingmodel(optional) — Model override
Returns: Draft narrative text, evidence recommendations, recommended issues, and prompt_version (which drafting instructions produced this output). Does not write to the platform.
The drafting agent is instructed to read the control’s rubric first — the evidence_expectations list from get_control_context (top-level, falling back to ai_guidance.evidence_expectations), compared against the target tier from scale_tier.tier or, on older platforms, get_scope’s target_scale_tier — and to account for every expectation at or below that tier. An independent observation that proves an expectation unmet becomes a complete Issue candidate; an expectation that is merely unverified goes to needs_input with one concrete next action rather than being silently omitted or mislabeled as an Issue.
Recommended issues come back in two forms:
recommended_issues[]— the canonical gap sentence, one short line each. This is the text to file as issue content. It is deliberately terse: the platform reconciler links a CLI-filed issue to its own later AI-review finding by comparing substance words, and a verbose issue scores too low to match, so the two end up filed twice.recommended_issues_detail[]— the admission contract for the same entries:expectation_key,unmet_expectation,observed_gap,observation_basis,risk_basis,inherent_likelihood,inherent_impact,clearance_condition,minimum_evidence,expectation_tier, optionaltarget_completion_date, plusadmittedand anyadmission_errors.needs_input[]— unverified expectations that lack an independent observation, each withexpectation_key,reason, and exactly onenext_action. These never become Issues merely because a Campaign evaluates them.
Campaign proposals submitted through submit_campaign_proposal are normalized to the same forms on the way in. Incomplete legacy candidates remain visible with admitted=false but cannot be written. Apply deduplicates admitted candidates, gives the canonical Issue its short matcher-safe text, and preserves the expectation, observation, clearance condition, and minimum evidence in a minimal draft treatment plan.
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.
update_scope_narrative
Replace the scope narrative sections for a system+framework. A completed scope is locked — call reopen_scope first (this returns a 422 scope_locked error otherwise). Pass the full ordered list of sections; each is an object with at least title and content.
Parameters:
system_id(required)framework_id(required)sections(required) — Full ordered list of narrative sections; each object hastitle,content, and optionalkey/order/parent_key.
Returns: Updated scope narrative.
reopen_scope
Reopen a completed scope for editing (regress it to in_progress). Records a monitoring regression event plus audit. Use before update_scope_narrative, answering questions, or regenerating when the scope is completed.
Parameters:
system_id(required)framework_id(required)
Returns: Updated scope state.
Policy Workflow
Custom policies are platform-native definitions, never promoted Evidence Locker items. Agents may author and submit them but cannot approve them.
create_custom_policy
Create from an explicit definition (title, purpose, version, ordered stable-ID
sections/questions) and optional is_required. Returns the created draft.
get_policy_definition
Read the definition state and revision for one policy_id. Use offset/limit
for bounded section and question pages; needs_configuration policies cannot
enter Q&A or generation.
update_policy_definition
Replace a definition with policy_id, definition, and expected_revision.
Set reset_authoring=true only after confirming the platform’s destructive reset.
suggest_policy_definition
Wait for an advisory definition suggestion from human-authored title, purpose,
and optional version. It never saves, submits, or approves the result.
get_policy_mappings
Read mappings for policy_id, optionally scoped by framework_id, using
offset/limit pagination.
replace_policy_mappings
Atomically replace family_mappings and control_mappings for one policy_id
within exactly one framework_id; mappings in other frameworks remain unchanged.
submit_policy_for_review
Submit a ready policy_id for first-party human review. This tool cannot approve.
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 contextinclude_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.
get_policy_narrative
Read an org policy’s generated narrative sections in order — the read counterpart
to update_policy_narrative. Use this before a surgical edit: read the current
sections, modify or append one, then pass the full list back so no existing
section is dropped. Large reads are paginated by default and never return
guard-generated content snippets. Use offset/limit to continue, set
include_content=false for a compact section index, or pass section_id to
fetch one complete section. This returns generated narrative sections, not the
Q&A template returned by get_org_policy_questionnaire.
Parameters:
policy_id(required)offset(optional, default0)limit(optional, 1–100, default10)include_content(optional, defaulttrue)section_id(optional; fetch one complete section)
Returns: {policy_id, sections[], pagination}. The pagination object
contains offset, limit, returned, total, has_more, and next_offset.
When include_content=false, each section contains only section_id, order,
and title.
search_policy_narrative
Search one org policy’s generated narrative for a natural-language concept.
This is the supported first step for “does this policy cover X?” questions:
use it before paging every section with get_policy_narrative, and before
editing. The search is policy-scoped and uses the platform’s policy-document
embeddings rather than loading or scanning the full policy catalog.
Parameters:
policy_id(required)query(required, 1–1000 characters) — Natural-language coverage question or conceptlimit(optional, 1–50, default5)min_similarity(optional, 0–1, default0.6)
Returns: {policy_id, query, total, matches, limit_reached}. Matches are
ordered by descending similarity and contain section_id, order, title,
similarity, and a short excerpt. An empty matches list means no section
met the requested similarity threshold.
update_policy_narrative
Replace an org policy’s generated narrative sections. An approved policy is locked — call reopen_policy first (this returns a 422 policy_locked error otherwise). Pass the full ordered list of sections; each is an object with section_id, title, and content.
Parameters:
policy_id(required)sections(required) — Full ordered list of policy sections; each object hassection_id,title,content, and optionalorder.
Returns: Updated policy narrative.
reopen_policy
Reopen an approved policy for editing (regress it to draft, clearing approval and bumping the version). Records a monitoring regression event plus audit. Use before update_policy_narrative, answering questions, or regenerating when the policy is approved.
Parameters:
policy_id(required)
Returns: Updated policy state.
Campaign Operations
Seven normal-profile coordinator tools expose the same Plan-backed Campaign
lifecycle as pretorin campaign. Both adapters call one transport-neutral
coordinator: equivalent normalized input freezes the same definition, roster,
preflight, authorized effects, confirmation digest, parent Plan, deterministic
child drafts, state transitions, cancellation behavior, projection, and domain
errors. A Campaign prepared by MCP can be started or watched by CLI, and a
Campaign prepared by CLI can be started, read, resumed, or cancelled by MCP.
MCP idempotency keys stay in a sidecar reservation and never enter the Campaign
record, Plan hierarchy, launch-definition digest, or lifecycle projection.
The tools do not add a platform Campaign API. Campaign state and execution are local to the host running the MCP server. Compliance artifacts and review remain authoritative on the platform, and completion never means that a control or objective was approved.
Observe an MCP-started Campaign in the TUI
Every result about one Campaign contains this informational handoff, with the actual validated Campaign Plan ID substituted:
{
"observer": {
"mode": "same_host_cli",
"command": "pretorin campaign watch <campaign-plan-id>",
"uvx_command": "uvx --from \"pretorin==0.29.10\" pretorin campaign watch <campaign-plan-id>",
"poll_tool": "get_campaign",
"same_host_required": true
}
}
The MCP server never executes either command. Run one in a terminal on the
same host as the MCP server to attach the read-only Textual observer; q
detaches without cancelling. The ordinary command is preferred when the
standard Pretorin package is installed. The version-matched base-package uvx
alternative supplies an isolated current-version environment. A remote MCP
client cannot attach to another host’s local Campaign store or migrate the run.
check_campaign_runtime
Inspect local Campaign execution readiness before preview. This is the first Campaign gate and is strictly read-only: it makes no platform calls, downloads, installations, idempotency reservations, Campaigns, or Plans.
Parameters:
agentoptionally selectscodexoropencode; otherwise the shared saved harness selection applies.model,model_provider, andreasoning_effortoptionally validate the same launch coordinates accepted by preview. Reasoning effort islow,medium, orhigh.
The response separates:
dependencies.execution, including the exact blocking Hatchet SDK pin;dependencies.observer, including non-execution Textual readiness;- selected native
runtimes,selection, and normalizedplatformfacts; blockers, which makelaunch_ready=falseand prevent preview;deferred_setup, for managed native components that may be installed only after the explicit start confirmation; anddeferred_validation, for a configured or PATH executable whose path and content identity are frozen now but whose version and capabilities are deliberately checked only after explicit start confirmation.
When launch_ready=false, do not call preview_campaign. Present the blocker
and structured remediation. A Python dependency blocker directs the operator
to pretorin update 0.29.10 and sets restart_mcp=true; after repair, restart the MCP
process and call check_campaign_runtime again. When launch_ready=true,
follow next_tool: "preview_campaign". Observer readiness is reported
separately and never substitutes for headless execution readiness.
preview_campaign
Prepare the exact Campaign that would be produced by CLI campaign start --dry-run, but only after check_campaign_runtime returns
launch_ready=true. Preview resolves platform scope and selector, performs the
one shared source preflight, and freezes immutable item order, child identities,
runtime/model/orchestrator policy, retries/concurrency, review policy, child
contract, exact authorized effects, draft parent/child Plan hierarchy, and the
confirmation digest. It does not activate Plans, install a runtime, dispatch a
worker, or make platform writes.
Parameters:
idempotency_key,campaign_type,system_id,framework_id, andselectorare required. The idempotency key is 1–200 characters.campaign_typeisinitial_pass,interim_pass,issue_triage, orevidence_review.selectoris a closedCampaignSelectorobject. Supply exactly one primary selector:all_controls,family_id,control_ids,all_open_issues,review_job_id, orevidence_ids. Issue selectors may also carryissue_source,issue_control_ids,issue_family_id, andinclude_resolved_issueswhen compatible with the Campaign type.- Optional launch coordinates include
project_dir,agent,model,model_provider,reasoning_effort,concurrency,max_retries, andrequest_platform_review(defaultfalse).
The response contains the Campaign Plan ID, confirmation digest, frozen exact
effects, aggregate counts, first immutable-order item page, continuation data,
and observer handoff. Reusing the same key with the same normalized request
returns the existing preview after restart once its frozen preparation has
been durably staged, without rerunning platform resolution or preflight.
Reusing it with different input returns campaign_idempotency_conflict; use a
new key for a new Campaign. A host failure during the initial external reads,
before their result can be atomically staged locally, may repeat those
read/preflight calls on recovery; the reserved Campaign ID is still reused and
no duplicate Campaign is created. Eliminating that final cross-system crash
window requires upstream transactional/idempotent preparation support.
start_campaign
Confirm and nonblockingly launch an existing draft prepared by either MCP or
CLI. Pass the exact campaign_plan_id, confirmation_digest, and
confirmed=true. The coordinator does not resolve the roster or rerun
preflight. It rechecks execution dependencies, validates the
frozen authority and runtime, durably records confirmation, activates the
parent/Campaign, ensures exactly one detached supervisor, and returns. Repeated
calls reconcile confirmation/activation crash windows without duplicating
execution. A changed or stale digest fails before mutation.
get_campaign
Read one Campaign by exact campaign_plan_id. Optional offset and limit
page its immutable item order (limit defaults to 10 and is at most 20). The
projection keeps the frozen definition, lifecycle, cancellation, objective,
execution, assessment, verified evidence-requirement coverage, and review axes
separate. Missing or corrupt child Plans receive explicit safe result codes
instead of changing the aggregate silently.
This read is local and remains available when platform authentication or consent is unavailable. It does not refresh platform data or imply compliance approval.
list_campaigns
List bounded Campaign summaries beneath authorized project roots. Optional
project_dir filters one root; limit defaults to 20 and is at most 50.
Results use stable (created_at, campaign_plan_id) ordering and an opaque
keyset cursor, not a mutable numeric offset. Incompatible pre-0.29.4
Plan-backed records are skipped and counted. Listing is local and does not
require current platform authentication or consent.
resume_campaign
Resume an exact campaign_plan_id. The call validates current platform
authority and the frozen runtime and Plan
hierarchy before mutation, adopts running work, submits unfinished work without
a live run, and reopens only eligible failures from completed_with_errors.
An unconfirmed draft returns campaign_confirmation_required; a durably
confirmed draft left in a crash window is repaired. The operation is
nonblocking and reuses the Campaign’s frozen configuration.
cancel_campaign
Durably request cancellation for an exact campaign_plan_id, with optional
bounded reason. Persistence happens before Hatchet/process delivery. The
shared result includes request_persisted,
delivery_state, current Campaign state, and rollback: false; a valid
persisted request may still be nonterminal when MCP returns. Cancellation is a
local operation that remains available during a platform auth or consent
outage. It never rolls back platform writes already committed.
Profiles, project roots, and bounded results
All seven lifecycle tools are coordinator tier with
requires_workflow=false, but are discoverable and dispatchable only in the
normal MCP profile. They are absent from both current and legacy
Campaign-worker profiles. Top-level start_task(intent_verb="campaign") is
route-only: it validates the requested scope, selects Campaign workflow
guidance, creates no generic Plan, and points the caller to
check_campaign_runtime. Only launch_ready=true points onward to
preview_campaign. An assigned child call carrying trusted parent_plan_id
and campaign_context retains the child-authored Plan protocol below.
When project_dir is omitted, MCP uses its canonical startup project root. An
explicit directory must exist beneath that root or one of the additional roots
in PRETORIN_MCP_ALLOWED_PROJECT_ROOTS (separated by : on POSIX and ; on
Windows). Filesystem roots, traversal, symlink escape, and Git roots outside an
authorized root are rejected. CLI derives the same canonical root from its
working directory, so nested paths and symlinks freeze identically.
Lifecycle payloads have an internal 32 KiB budget beneath the server-wide guard. Pages may contain fewer rows than their requested limit and return continuation metadata to stay within that budget. Responses include bounded labels and scope summaries, safe IDs, counts, states, result codes, timestamps, durability, and the observer handoff. They exclude credentials, evidence or preflight bodies, raw receipts/limitations/errors/events, hidden reasoning, unrestricted agent output, and full Plan prose.
Shared domain error codes include campaign_invalid_request,
campaign_invalid_project, campaign_idempotency_conflict,
campaign_not_found, campaign_state_version_unsupported,
campaign_confirmation_required, campaign_confirmation_mismatch,
campaign_confirmation_stale, authority/runtime/hierarchy drift,
campaign_invalid_state, campaign_launch_failure, and
campaign_cancellation_delivery_failure.
Assigned child tools
Plan-backed Campaign children use the normal workflow, Plan, recipe,
compliance-writer, and platform-review tools. Each Codex or OpenCode child
receives the internal campaign-worker MCP profile and a trusted frozen
assignment. It calls start_task, fetches the selected workflow,
and authors and activates its own concrete child Plan around the mandatory
assignment milestones. The profile permits only assigned reads, workflow and
child Plan lifecycle, the coordinator-owned read-only preflight snapshot,
recipe operations, required typed Plan-scoped
writers, and the bounded process-record tools below. It rejects cross-item
access, Campaign finalization, evidence deletion, human approval, and the generic
proposal/apply path.
Every mutating process-record call, plus the Issue/evidence inspection calls,
requires the assigned child plan_id and current non-negative step_index and
is fenced to the latest running assignment attempt. Receipt inspection requires
the child plan_id and can optionally filter by writer. These records contain
process facts and platform resource IDs only; platform artifact bodies remain
authoritative on the platform.
record_campaign_preflight
Deprecated compatibility tool for Campaign records created before shared
preflight snapshots. Current campaign-worker profiles do not expose it.
Pretorin now prepares the ordinary preflight once before dispatch and each
child reads an immutable copy with get_preflight and get_active_recipes.
Parameters:
plan_id(required) — Assigned child Plan IDstep_index(required) — Current child Plan stepstatus(required) —mapped,degraded, orunavailableconnections_checked(optional) — Bounded connection identifierssource_kinds(optional) — Bounded source kinds examinedrecipes(required) — Decisions withrecipe_id,decision(selected,skipped, orunavailable), and a boundedreasonsearches(optional) — Bounded searches performedlimitations(optional) — Coverage limitations safe for the observer
For a legacy assignment, caller fields for status, connections, source kinds, and searches are compatibility inputs, not authority. This compatibility path normalizes them from its local snapshot and Plan signals. It is not part of new Campaign preparation or execution.
record_campaign_objective_disposition
Record exactly one outcome for an assessment-objective UUID in the frozen item roster.
Parameters:
plan_id,step_index(required)objective_uuid(required) — Must be in the trusted assignmentdisposition(required) —grounded,gap,needs_input, ornot_applicableevidence_ids(optional) — Persisted platform evidence IDs; required forgroundedlimitations(optional) — Required forneeds_inputissue_id(optional) — Governed platform Issue created for an independently observed gap
mixed is an aggregate assessment state and is not valid for one objective.
Evidence requests belong in limitations/next actions, never evidence_ids.
inspect_campaign_issue
Read the exact canonical Issue frozen into an issue_triage child. The server
derives the Issue and owning control-implementation identities from the trusted
assignment; callers cannot substitute another Issue.
Parameters: plan_id and the current step_index.
record_campaign_issue_disposition
Record one governed outcome for that frozen Issue after re-reading its current platform lifecycle and evidence.
Parameters: plan_id, step_index, disposition (verified,
action_required, already_terminal, or needs_input), reason, optional
next_action, evidence_ids, and limitations. verified requires a closed
Issue and persisted verification evidence; action_required names one concrete
next action; needs_input names a limitation. This tool cannot approve
treatment, accept risk, or void an Issue.
inspect_campaign_evidence
Read the exact artifact frozen into an evidence-ID review child. A control
evidence-set child instead uses assignment-scoped search_evidence; neither
form can enumerate another Campaign item’s evidence.
Parameters: plan_id and the current step_index.
record_campaign_evidence_disposition
Record retained, remapped, superseded, or needs_input for the frozen
artifact or evidence set. The handler verifies every evidence ID remains inside
the assigned control. A remap requires its typed evidence-link artifact, while
superseding records replacement IDs without deleting the prior evidence.
Parameters: plan_id, step_index, disposition, reason,
evidence_ids, optional target_control_id, superseding_evidence_ids, and
limitations.
record_campaign_assessment
Record the independent assessment axis for an assigned item that has no frozen objective roster. Objective-backed items derive their aggregate from the exact objective dispositions instead.
Parameters: plan_id, step_index, assessment, and optional
limitations. needs_input requires a limitation.
inspect_campaign_resource_receipts
Read the assigned child’s bounded, content-free typed-write receipt ledger and matching child-Plan artifacts before retrying an uncertain write. This is the reconciliation surface for lost platform responses; it never returns artifact bodies.
Parameters: plan_id and an optional typed-writer tool filter.
record_campaign_resource_receipt
Record an explicit skipped or terminal outcome that no typed writer can observe. Normal Campaign evidence, mapping, narrative, objective, and Issue writers create and reconcile their own intended-to-terminal receipts automatically; callers must not pre-claim those logical keys.
Parameters:
plan_id,step_index(required)step_refandlogical_artifact_key(required) — Combined with parent/child Plan identity and structural version to derive the idempotency keytool(required) — Existing typed MCP writer usedstatus(required) —intended,succeeded,replayed,terminal_error, orskippedpayload_digest(required) — SHA-256 of the bounded intended payloadresource_id— Required forsucceededandreplayedresult_code(optional) — Bounded 1–100 character safe token ([A-Za-z0-9_.:-]) recording the outcome reason, e.g. the terminal error class forterminal_error
Manual records live in a disjoint manual: logical namespace and cannot suppress
a typed mutation. A receipt is not a second copy of the platform resource.
Automatic replay revalidates the typed authoritative platform read; it does not
trust a stale local terminal row by itself. The broader status enum is retained
for reconciliation compatibility, but normal workers use this manual surface
only for skipped or terminal_error; succeeded/replayed are accepted only
when the child Plan already contains the matching authoritative typed-writer
artifact.
record_campaign_review
Record the existing platform review job associated with the assigned item.
Parameters: plan_id, step_index, state, optional job_id, positive
generation, and platform destination. A requested state requires a job ID.
Control Campaigns require the exact job/generation pair already attributed on
the assigned child Plan, verify it against the live platform review result, and
require its target generation to equal the control’s current narrative
generation. An older successful review can never satisfy the final-generation
gate. This record never represents a human approval.
Legacy compatibility tools
prepare_campaign, claim_campaign_items, update_campaign_item_phase,
get_campaign_item_context, submit_campaign_proposal, apply_campaign, and
checkpoint-based get_campaign_status remain compatibility-only for the
0.29.x release line and will not be removed before 0.30.0. They are absent from
the normal worker profile. New Campaigns must use the parent/child Plan
lifecycle and existing typed writers directly.
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,avoidtreatment_plan(optional)treatment_due_date(optional) — ISO date stringreview_frequency_days(optional) — How often the risk should be re-reviewedframework_id(optional) — Required for control auto-linksuggested_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,avoidtreatment_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_riskcontrol_id(optional) — Pair withframework_idframework_id(optional) — Required when linking a controlevidence_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.
get_risk_posture
Read the system’s aggregate risk-assessment posture: inherent and residual distributions, weighted residual score, overdue reviews, and top risks.
Parameters:
system_id(required)
Returns: Aggregate posture summary.
review_risk
Record an explicit completed review of one risk and reset its review cadence. Use only after inspecting the risk, its linked controls and evidence, its scoring, and its treatment — this is the attestable “a human-directed agent looked at this” signal, not a bookkeeping touch.
Parameters:
system_id(required)risk_id(required)
Returns: The reviewed risk entry with its refreshed review timestamps.
attest_risk
Produce a DSSE-signed attestation over the current reviewed risk state. The server rejects stale or missing reviews, so review_risk must come first; any mutation after that review requires another explicit review before attesting again.
Parameters:
system_id(required)risk_id(required)attestation_type(required) —residual_accepted,mitigation_approved, orinherent_validatedattestation_statement(required) — Auditor-facing rationale for the signed determination; it must explain the determination, not restate the risk
Returns: The signed attestation envelope.
list_risk_attestations
List signed risk-attestation envelopes newest first for audit verification.
Parameters:
system_id(required)risk_id(required)
Returns: Attestation envelopes, newest first.
generate_risk_assessment_report
Synchronously generate or idempotently reuse the current Risk Assessment
Report (RAR) for the active system/framework. This is a governed write and must
follow the risk-assessment workflow selected with
start_task(intent_verb="risk_assessment", ...).
Parameters:
system_id(required)framework_id(required) — Must match the active frameworkforce_regenerate(optional) — Defaultfalse; set only when a new document version is explicitly required
Returns: Current RAR document id, status, generation timestamp, and
already_generated replay indicator.
get_risk_assessment_report
Read metadata for the current RAR in the active system/framework scope. This is a proof-only call: it never creates, repairs, or regenerates a document, and it returns not found when no current RAR exists.
Parameters:
system_id(required)framework_id(required) — Must match the active framework
Returns: Current RAR id, name, version, status, generation timestamp, completeness, warnings, section count, AI-generated flag, and timestamps.
Formal Assessments and Auditor Portal
Use start_task(intent_verb="formal_assessment", ...) and load the
formal-assessment workflow before scheduling or starting an assessment.
Every assessment_type below is one of self_assessment, third_party,
continuous, annual_review, readiness, or gap_analysis.
list_assessments
List formal assessments for one system with optional type/status filters.
Parameters:
system_id(required) — System ID or nameassessment_type(optional) — One assessment type to filter bystatuses(optional) — Array of status filterslimit(optional) — Default:100offset(optional) — Default:0
get_assessment
Read one formal assessment, including status and immutable snapshot state.
Parameters:
system_id(required) — System ID or nameassessment_id(required)
schedule_assessment
Schedule a formal assessment in the active system/framework scope. This accepts planning facts only; assessment outcomes and final report links cannot be predeclared. Identical engagement requests are atomically deduplicated by the public integration; replay the same call and require the same assessment ID before starting it.
Parameters:
system_id(required) — System ID or namename(required) — Engagement nameassessment_type(required)framework_id(required) — Active framework IDdescription(optional)scheduled_start_date,scheduled_end_date(optional)assessor_organization,assessor_contact(optional)notes(optional)
start_assessment
Start a scheduled assessment and initiate its immutable snapshot. Poll
get_assessment until the assessment is in_progress and its snapshot is
frozen before claiming the read-only Auditor Portal is ready.
Parameters:
system_id(required) — System ID or nameassessment_id(required)
System Spec Artifacts
Auditor-required artifacts (asset inventory plus four snapshot kinds) that anchor a system’s audit chain. See System Spec Artifacts for the full schema.
list_artifact_requirements
List the 5 auditor-required system_spec artifact kinds for a system (asset inventory + 4 snapshot kinds). Returns each kind’s effective_required, optional/toggled-off state, attestation timestamp, and rationale.
Parameters:
system_id(required)
Returns: Artifact-requirement rows with required/optional state and attestation metadata.
get_asset_inventory
Return the system’s asset inventory. Active rows by default; pass as_of (ISO-8601 timestamp) to replay historical state.
Parameters:
system_id(required)as_of(optional) — ISO-8601 timestamp for historical replay
Returns: Asset inventory rows with provenance and snapshot timestamp.
submit_asset_inventory_diff
Submit an asset-inventory diff produced by a recipe-driven scan. At least one of added / modified / decommissioned must be non-empty. recipe_id is a free-form CLI string the platform records as cli:<recipe_id> provenance per row. idempotency_key defaults to sha256(system_id, recipe_id, scan_timestamp); pass your own when replaying a scan. recipe_context_id (from start_recipe) is optional — the diff endpoint accepts it cleanly but does not require it.
Parameters:
system_id(required)recipe_id(required) — Free-form CLI recipe id (e.g.,asset-inventory-aws-baseline); stored as provenance per rowidempotency_key(optional) — Defaults tosha256(system_id, recipe_id, scan_timestamp)[:32]recipe_context_id(optional) — UUID returned bystart_recipewhen the diff is produced inside an active recipe contextadded(optional) — Array of new asset rows. Required per row:external_id. Recommended:name,asset_type,environment,data_classification,criticalitymodified(optional) — Array of changed asset rows keyed byexternal_id; same shape asaddeddecommissioned(optional) — Array of{external_id, rationale}for assets to mark decommissioned
Returns: Diff acceptance summary with per-row outcomes.
link_spec_snapshot
Link an uploaded evidence item as the current snapshot for a system_spec kind, so it surfaces on the scope page. Use after upload_evidence returns an evidence id. kind is one of the snapshot kinds (boundary_diagram, network_dfd, ppsm, interconnection) — call list_artifact_requirements for the authoritative set. The asset inventory is not a snapshot kind (attest it with attest_spec_inventory). Requires an active workflow (call start_task first).
Parameters:
system_id(required)kind(required) — Snapshot kind to link the evidence toevidence_id(required) — ID of the uploaded evidence item to link as this kind’s snapshotplan_id(optional) /step_index(optional) — B3 plan attribution
Returns: The updated snapshot-kind state.
attest_spec_snapshot
Attest a system_spec snapshot kind (boundary_diagram, network_dfd, ppsm, interconnection), setting its last_attested_at on the scope page. Typically called right after link_spec_snapshot. Requires an active workflow.
Parameters:
system_id(required)kind(required) — Snapshot kind to attestevidence_id(optional) — The linked evidence item being attestedsufficiency(optional) — Auditor sufficiency envelope (canonical source, coverage window, producer, verification state)plan_id(optional) /step_index(optional) — B3 plan attribution
Returns: The updated snapshot-kind attestation state.
attest_spec_inventory
Attest the current asset inventory state, setting its last_attested_at on the scope page. Use after submit_asset_inventory_diff has the inventory in the desired state. The inventory is a living kind (rows + attestation), not a file upload — there is no evidence_id. Requires an active workflow.
Parameters:
system_id(required)sufficiency(optional) — Auditor sufficiency envelopeattestation_name(optional) — Human-readable label for this inventory attestationplan_id(optional) /step_index(optional) — B3 plan attribution
Returns: The inventory attestation result.
Vendor Management
list_vendors
List all vendor entities in the organization. The client fetches every matching page from the paginated public API.
Parameters:
search(optional) — Case-insensitive match on name/descriptionprovider_type(optional) —csp,saas,managed_service,internalrisk_tier(optional) —low,moderate,high,criticalowner_user_id(optional)assessment_status(optional) —draft,in_progress,submitted,reviewedlifecycle_status(optional) —onboarding,active,inactiveinclude_inactive(optional) — Include inactive vendors, which are hidden by default. Default:falsesort_by(optional) —name,provider_type,inherent_risk,risk_tier,residual_risk_score,next_review_at,last_assessed_at,created_at,document_count. Default:namesort_dir(optional) —asc,desc. Default:asc
Returns: Vendor list with IDs, names, types, authorization levels, inherent risk, residual tier, lifecycle status, reassessment dates, assessment status, document-expiry flags, and document counts when provided by the platform. Inactive vendors are omitted unless include_inactive is set.
create_vendor
Create a new vendor entity.
Parameters:
name(required)provider_type(required) —csp,saas,managed_service,internaldescription(optional)authorization_level(optional)owner_user_id(optional)inherent_risk(optional) —low,moderate,high,critical;mediumis a deprecated alias formoderate
Returns: Created vendor record.
get_vendor
Get vendor details.
Parameters:
vendor_id(required)
Returns: Vendor metadata and linked documents.
get_vendor_history
Get vendor audit and evidence history.
Parameters:
vendor_id(required)limit(optional) — 1..500. Default: 100
Returns: Vendor history events.
get_vendor_dashboard
Get the organization-wide third-party-risk (TPRM) reporting dashboard: posture counts, by_tier / by_provider_type breakdowns, the 5×5 residual likelihood×impact heatmap, and bounded document/contract expiry lists. Organization-wide — requires an org-scoped token with the vendor.pii or admin scope; system-scoped tokens are rejected.
Parameters:
horizon_days(optional) — 1..365. Default: 90. Look-ahead window for the expiring-soon KPIs and lists.
Returns: A VendorTprmSummary. Note: per-cell heatmap vendor rosters are omitted to stay within the MCP response-size budget (heatmap_vendors_omitted is set to true); each cell still carries its vendor count. Call list_vendors with a risk_tier filter to enumerate the vendors in a tier.
update_vendor
Update vendor fields.
Parameters:
vendor_id(required)name(optional)description(optional)provider_type(optional) —csp,saas,managed_service,internalauthorization_level(optional)owner_user_id(optional)inherent_risk(optional) —low,moderate,high,critical;mediumis a deprecated alias formoderate
Returns: Updated vendor record.
set_vendor_lifecycle
Transition a vendor to a new lifecycle status. Requires the server-side vendor.pii
scope (or an admin token); the platform returns 403 if the token is not authorized.
Parameters:
vendor_id(required)target_status(required) —onboarding,active,inactivereason(required) — Non-empty audit reason, max 500 characters
Returns: Updated vendor record with its new lifecycle status.
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_providedexpires_at(optional) — Document expiry date (ISO-8601, e.g.2027-01-31)refresh_cadence_days(optional) — Refresh reminder cadence in days (1–365)
Returns: Uploaded document record.
list_vendor_documents
List documents linked to a vendor.
Parameters:
vendor_id(required)
Returns: Document list with metadata.
list_vendor_contacts
List a vendor’s contacts. Requires the server-side vendor.pii scope (or an admin token); the platform returns 403 if the token is not authorized.
Parameters:
vendor_id(required)
Returns: Contact list.
create_vendor_contact
Add a contact to a vendor. Requires the vendor.pii scope. Setting is_primary auto-demotes the prior primary contact.
Parameters:
vendor_id(required)name(required)email(optional)title(optional)phone(optional)is_primary(optional, boolean)notes(optional)
Returns: The created contact.
update_vendor_contact
Update a vendor contact. Requires the vendor.pii scope. Only provided fields are updated.
Parameters:
vendor_id(required)contact_id(required)name,email,title,phone,is_primary,notes(all optional)
Returns: The updated contact.
delete_vendor_contact
Delete a vendor contact. Requires the vendor.pii scope.
Parameters:
vendor_id(required)contact_id(required)
Returns: Deletion confirmation.
list_vendor_contracts
List a vendor’s contracts, SLAs, and DPAs. Requires the vendor.pii scope. status and is_expired are server-derived, read-only fields.
Parameters:
vendor_id(required)
Returns: Contract list including derived status and is_expired.
create_vendor_contract
Add a contract to a vendor. Requires the vendor.pii scope. status and is_expired are server-derived and cannot be set.
Parameters:
vendor_id(required)name(required)contract_type(required) —contract,sla,dpa,order_formstart_date,end_date,renewal_date(optional, ISO-8601)auto_renew(optional, boolean)notice_period_days(optional, integer)terminated_at(optional, ISO-8601)document_evidence_item_id(optional)notes(optional)
Returns: The created contract.
update_vendor_contract
Update a vendor contract. Requires the vendor.pii scope. Only provided fields are updated. status and is_expired are server-derived and cannot be set.
Parameters:
vendor_id(required)contract_id(required)name,contract_type,start_date,end_date,renewal_date,auto_renew,notice_period_days,terminated_at,document_evidence_item_id,notes(all optional)
Returns: The updated contract.
delete_vendor_contract
Delete a vendor contract. Requires the vendor.pii scope.
Parameters:
vendor_id(required)contract_id(required)
Returns: Deletion confirmation.
list_vendor_systems
List the systems a vendor serves.
Parameters:
vendor_id(required)
Returns: List of attached systems with total.
attach_vendor_systems
Attach one or more systems to a vendor (SR-5 / SA-9 system-of-record mapping).
Parameters:
vendor_id(required)system_ids(required) — array of system IDs (at least one)
Returns: Attachment result.
detach_vendor_system
Detach a system from a vendor.
Parameters:
vendor_id(required)system_id(required)
Returns: Detachment confirmation.
sign_vendor_residual_acceptance
Sign authorizing-official acceptance of a vendor’s residual risk for one attached system. Idempotent per (vendor, system). Requires the org’s evidence attestation-envelope capability and attestation process mode; when signing is disabled the tool returns a clear, actionable error.
Parameters:
vendor_id(required)system_id(required) — attached system ID to accept residual risk fornote(optional) — justification/note for the acceptance
Returns: The signed residual-acceptance result.
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 unlinkattestation_type(optional) —self_attested,third_party_attestation,vendor_provided
Returns: Link confirmation.
list_vendor_assessment_templates
List vendor assessment templates available to the organization.
Parameters: None.
Returns: Template summaries including kind, source format, section count, and question count.
get_vendor_assessment_template
Get a vendor assessment template with its full section and question specs.
Parameters:
template_id(required)
Returns: Template detail, including sections, questions, and in_flight_assessment_count.
import_vendor_assessment_template
Import a SIG-Lite or CAIQ-Lite xlsx workbook as an org-scoped vendor assessment
template. The default dry-run returns a preview. To persist the template, pass
dry_run=false and acknowledge_license_rights=true.
Parameters:
file_path(required) — Local.xlsxworkbook pathsource_format(required) —sig_lite,caiq_litedry_run(optional) — Default:trueacknowledge_license_rights(optional) — Required whendry_run=false
Returns: Import preview on dry-run, or created template summary when persisted.
delete_vendor_assessment_template
Delete an org-scoped custom or imported vendor assessment template. Global seed templates cannot be deleted.
Parameters:
template_id(required)
Returns: Deletion confirmation.
launch_vendor_assessment
Launch an assessment against a vendor, freezing the selected template snapshot.
Parameters:
vendor_id(required)template_id(required)
Returns: Assessment summary.
list_vendor_assessments
List assessments run against a vendor.
Parameters:
vendor_id(required)
Returns: Assessment summaries, including review_revision. A positive
revision while status is not reviewed identifies a reopened assessment whose
residual ratings and risk tier describe a prior, superseded review.
get_vendor_assessment
Get an assessment with its frozen template snapshot, responses, and any advisory AI summary.
Parameters:
vendor_id(required)assessment_id(required)
Returns: Assessment detail, including review_revision. A positive revision
while status is not reviewed means residual_likelihood, residual_impact,
and risk_tier belong to the prior, superseded review rather than the current
in-progress assessment.
save_vendor_assessment_responses
Upsert assessment answers. The first answer moves a draft assessment to
in_progress.
Parameters:
vendor_id(required)assessment_id(required)answers(required) — List of answer objects withquestion_ref; optional fields areanswer,comment, andevidence_item_id
Returns: Updated assessment detail.
submit_vendor_assessment
Move an in-progress vendor assessment to submitted.
Parameters:
vendor_id(required)assessment_id(required)
Returns: Assessment summary.
score_vendor_assessment
Run advisory AI scoring over a submitted assessment. If scoring is unavailable, the platform records that state and review can still proceed through the acknowledgement gate.
Parameters:
vendor_id(required)assessment_id(required)
Returns: Assessment detail.
review_vendor_assessment
Finalize an assessment by setting residual likelihood and impact. Values use the
five-point NIST 800-30 scale: very_low, low, moderate, high,
very_high. Every successful finalization increments review_revision and
retains its signed review record; a later review supersedes rather than
overwrites it.
Parameters:
vendor_id(required)assessment_id(required)residual_likelihood(required) —very_low,low,moderate,high,very_highresidual_impact(required) —very_low,low,moderate,high,very_highacknowledge_no_ai_review(optional) — Required to finalize when no successful AI advisory summary exists
Returns: Reviewed assessment summary.
reopen_vendor_assessment
Reopen a reviewed vendor assessment for correction, moving it back to
in_progress without creating a new assessment. Supply exactly one vendor
selector: vendor_id, or vendor_name for a unique exact case-insensitive
match. Reopening from any status other than reviewed returns an actionable
conflict.
Reopening revokes any live vendor-portal token and resets the AI advisory to
not_run, dropping its summary and basis. Run score_vendor_assessment again
before the next review or explicitly set acknowledge_no_ai_review=true when
re-finalizing. The prior completed review remains on the assessment as a
superseded revision; when review_revision > 0 and status is not reviewed,
the returned residual ratings and risk tier are historical, not current.
Parameters:
vendor_id(conditional) — Vendor ID; pass exactly one ofvendor_idorvendor_namevendor_name(conditional) — Unique exact vendor name, matched case-insensitively; pass exactly one vendor selectorassessment_id(required)reason(optional) — Audit reason, at most 255 characters; blank input is omitted
Returns: Full updated assessment detail with status="in_progress" and the
retained review_revision.
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) —inheritedorsharedsource_type(optional) —providerfor a vendor entry on the Pretorin vendor portal, ororg_systemfor an org-internal systemvendor_id(conditional) — Vendor provider id from the vendor portal. Required whensource_typeisprovidersource_system_id(conditional) — Source org-internal system id. Required whensource_typeisorg_systemsource_control_id(optional) — Control id on the source side. Defaults to the targetcontrol_id, which fits the common vendor-inheritance case where the source covers the same control concept
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 areaproduct(optional) — Filter by product namelimit(optional) — Default:100offset(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 identifierlimit(optional) — Default:100offset(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:100offset(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_summary
Get the bounded CCI implementation authoring and approval posture for one
active system/framework. This is distinct from get_cci_status, which reports
STIG scan results.
Parameters:
system_id(required)framework_id(optional) — Defaults to the active MCP framework and must match the active context when supplied.
Returns: In-scope initialized CCI implementation total, approved,
unapproved, and effective status_counts, excluding deprecated catalog CCIs
and archived implementations.
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 theCCI-000XXXlabel)
Returns: Full CCI implementation detail.
update_cci_implementation
Commit agent-authored working fields for one CCI before approval. Ordinary updates may only set status=in_progress; the explicit completion decision goes through approve_cci_implementation. This operation never approves the parent control.
Parameters:
system_id(required)cci_uuid(required) — CCI catalog UUID, not theCCI-000XXXdisplay labelstatus(optional) — Onlyin_progressis accepted herenarrative(optional)responsible_entities(optional, max 500 chars)tested_by(optional, max 255 chars)test_date(optional) — ISO 8601 date-timeassessment_procedure(optional, max 100 chars)evidence_ids(optional) — Array of evidence IDsreason(optional, max 500 chars)
Returns: The updated CCI implementation row.
approve_cci_implementation
Explicitly and idempotently approve one CCI implementation. The CCI must already be past not_started with a substantive committed narrative and approval-supporting scoped evidence (verified, checksummed pending recipe evidence, or valid evidence); otherwise the server returns 409 listing the missing prerequisites. Approval is recorded with agent source and approval stamps. This does not approve the parent NIST/DoD control — a human does that in the UI.
Parameters:
system_id(required)cci_uuid(required) — CCI catalog UUID, not theCCI-000XXXdisplay label
Returns: The approved CCI implementation row.
approve_stig_rule_workflow
Explicitly and idempotently approve the workflow for one exact STIG rule. Four prerequisites must all hold, or the server returns 409 naming the missing ones: the rule is in scope through confirmed applicability or a checklist, its latest exact-rule result passes, verified/checksummed recipe remediation evidence (or valid evidence) is linked to the workflow, and every linked Issue is reconciled.
Parameters:
system_id(required)stig_rule_id(required) — Internal STIG rule UUID for the exact rule (from the traceability or checklist surfaces), not theSV-...display id
Returns: The approved STIG rule workflow row.
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 benchmarkrule_id(optional) — Exact DISA rule ID or internal rule UUIDmode(optional) —full(default) orsummarylimit/offset(optional) — Bounded rule pagination; summary defaults to 25 rules
Returns: Test manifest with applicable rules and scanner assignments plus
response_metadata containing filters, page counts, has_more, next_offset,
and an explicit truncated flag. Use stig_id + rule_id in full mode for one
complete scanner definition; use summary mode to omit check/fix bodies while
browsing.
submit_test_results
Upload STIG scan results to the platform.
Parameters:
system_id(required)cli_run_id(required) — CLI scan run identifierresults(required) — Array of test result objectscli_version(optional) — CLI version stringframework_id(optional) — Active framework ID used for exact Issue attribution. Supply it for compliance scans.
Returns: Submission confirmation with per-result status.
list_stig_checklists
List STIG checklists for a system (per-asset: benchmark, asset identity, title). Use to discover an existing checklist_id before export/import, or to confirm one exists for a (benchmark, asset) pair before creating a new one.
Parameters:
system_id(required)inventory_item_id(optional) — Filter to one asset’s checklists by inventory item IDlimit(optional) — Max results per page (1–500). Default:100offset(optional) — Pagination offset. Default:0
Returns: Checklist summaries (benchmark, asset identity, title, id).
create_stig_checklist
Create an asset-scoped STIG checklist bound to a benchmark + asset. Returns the new checklist summary (including its id). Fails if one already exists for that (benchmark, asset), or if the benchmark/asset is unknown. Create-or-resolve a checklist this way before importing scanner output.
Parameters:
system_id(required)stig_benchmark_id(required) — STIG benchmark ID to bind (e.g.RHEL_9_STIG)inventory_item_id(required) — Asset inventory item ID to bind the checklist totitle(optional) — Checklist title
Returns: The new checklist summary including its id.
export_stig_checklist
Export a checklist to a local file as DISA .ckl (XML) or .cklb (JSON). Regenerated on demand (air-gap/FIPS-safe; no eMASS connector needed). Writes to output_path and returns {path, format, size_bytes, sha256} — the raw file is written to disk, not inlined in the response. Refuses an existing output_path unless overwrite=true, and never writes through a symlink.
Parameters:
system_id(required)checklist_id(required) — Checklist ID to exportoutput_path(required) — Local path to write the exported checklist fileformat(optional) —ckl(XML) orcklb(JSON). Default:ckloverwrite(optional) — Replaceoutput_pathif it already exists. Default:false
Returns: {path, format, size_bytes, sha256} for the written file.
import_stig_checklist
Import a .ckl/.cklb file into a checklist’s per-rule reviews (review axis). Full-fidelity complement to submit_test_results: ingests asset metadata, the four DISA statuses, finding details/comments, and severity override, reconciled against the benchmark. A non-reconciling import (rules dropped) returns an error result — never treat it as complete. Writes are refused outside the active context system.
Parameters:
system_id(required)checklist_id(required) — Target checklist ID (must already exist)file_path(required) — Local path to the.ckl(XML) or.cklb(JSON) fileformat(optional) —auto,ckl, orcklb. Default:auto
Returns: Match/import counters, a reconciles flag, and capped rule-id buckets (full per-rule detail via the CLI).
import_stig_checklist_xccdf
Import an XCCDF scan document (SCAP/OpenSCAP results) into the system test axis. Separate from import_stig_checklist (the .ckl/.cklb review axis). The test axis is system-scoped, so the response reports how many checklists on the system the scan affects. Use this to push a scanner recipe’s XCCDF results so they derive DISA statuses across all checklists bound to the same benchmark.
Parameters:
system_id(required)checklist_id(required) — A checklist ID on the target systemfile_path(required) — Local path to the XCCDF results document
Returns: Import summary reporting how many checklists on the system the scan affects.
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). Deprecated compatibility recipes are hidden by default. 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, orcommunityproduces(optional) — Filter by what the recipe produces:evidence,narrative,both,answers, orissues(notesis a legacy compatibility value)system_id(optional) — Filter to recipes runnable against the system’s connected sources; also annotates each recipe with anactiveflag (membership in the scope’s active set)include_unavailable(optional) — Include recipes missing required sources with unavailable reasons. Default:falseinclude_deprecated(optional) — Include deprecated compatibility recipes and their replacements. Default:falseactive_only(optional) — Whensystem_idis supplied, return only the scope’s active recipe set. On an unprovisioned or missing scope this returns an empty recipe list, not the whole cookbook. Default:false
Returns: Recipe summaries with manifest metadata, required sources, per-recipe source availability, and an active flag when a system scope is supplied.
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 bystart_taskcontrol_id(required)system_id(optional) — Defaults to active scopeframework_id(optional) — Defaults to active scopeinclude_source_hints(optional) — Return full per-expectationsource_hintsinstead of compact hint summaries. Default:false
Returns: Compact capture-plan items with source kind, connected state, candidate recipes, selected recipe, and structured recipe_gap entries. On a provisioned scope, candidates are drawn from the active recipe set and each recipe_gap carries ready_source_kinds and ready_alternative_recipe_ids so an unmatched hint points at substitutes instead of a dead-end. Full source_hints are opt-in via include_source_hints=true.
get_active_recipes
Read the scope’s active recipe set — the curated subset of the cookbook provisioned for this (system, framework) compliance effort — plus a provisioning proposal. Call this during preflight (workflow Step 7) to seed the set, and whenever deciding what to run.
Parameters:
system_id(optional) — Defaults to active scopeframework_id(optional) — Defaults to active scope
Returns: active (the provisioned recipes), candidates (recipes runnable on this host, each with serves_kinds), coverage_gaps (ready source kinds no recipe consumes), and drift (active recipes whose pinned version/content/source has moved or left the cookbook). Returns provisioned: false / exists: false when the scope has no preflight artifact yet.
set_active_recipes
Edit the scope’s active recipe set and persist it on the preflight artifact. Seed it from get_active_recipes candidates during preflight, then adjust as the effort evolves. Establishing an active set makes it the confirmed menu: start_recipe then refuses recipes outside it (unless force=true), and the capture plan draws candidates from it.
Parameters:
recipe_ids(required) — Recipe ids to set/add/remove (may be empty only formode='replace')mode(optional) —replace(default, set the active set to exactlyrecipe_ids),add, orremovesystem_id(optional) — Defaults to active scopeframework_id(optional) — Defaults to active scope
With mode='add', an already-active recipe whose version and loader source are
unchanged but whose reviewed content digest moved is re-pinned. Version and
loader-source drift require an explicit remove followed by add after review.
Returns: The activated/deactivated/unchanged ids, repinned records with old
and new content hashes, any unknown_recipe_ids skipped (not in the cookbook),
and the resulting active set.
start_recipe
Open a recipe execution context. Returns a context_id the caller passes as recipe_context_id on subsequent platform-API write tool calls and to end_recipe 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. On a provisioned scope, start_recipe refuses recipes outside the active set and active recipes whose pinned version/content/source has drifted; pass force=true only for an audited ad-hoc run.
Parameters:
recipe_id(required) — Recipe id (must be loadable from the registry)recipe_version(required) — Recipe version the caller intends to run. Read this fromget_recipe(recipe_id).manifest.version(or theversionfield returned bylist_recipes) before calling — hard-coded values will break when the recipe registry advances. Cross-checked against the loaded recipe; mismatch is an error.params(optional) — Inputs the calling agent supplies, validated against the recipe’s params schemaselection(optional) — StructuredRecipeSelectionrecord from the engagement layer, stored on the context for the eventualRecipeResultevidence_ids(optional) — Evidence ids supplied as inputs for narrative-producing recipessystem_id(optional) — Defaults to active scopeframework_id(optional) — Defaults to active scopecontrol_id(optional) — Control context for the recipe runforce(optional) — Open the context ad hoc when preflight source availability, active-set membership, or active recipe drift would otherwise refuse the run. Forced runs are recorded on the execution record.
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:
recipe_context_id(required unless using the deprecated alias) — Context id returned bystart_recipe; use this canonical name to matchupdate_narrative,add_control_issue, andresolve_control_issuecontext_id(optional, deprecated) — Legacy alias accepted for backwards compatibility. Preferrecipe_context_id.status(optional) — Caller-supplied disposition:pass,fail, orneeds_input. Default:pass
Returns: RecipeResult summary.
list_workflows
List loaded workflow playbooks (single-control, scope-question, scope-artifacts, policy-question, campaign, preflight, stig-scan-remediation, risk-assessment, formal-assessment). 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,campaign_items,system_spec_kinds,source_kinds,stig_rules,system_risks, orassessments
Returns: Workflow summaries with manifest metadata.
get_workflow
Return one workflow’s manifest, Markdown instructions, and referenced tool schemas.
Parameters:
workflow_id(required) — Workflow id to fetchmode(optional) —full(default) or validation-equivalentcompactsection(optional) — Heading title/id fromresponse_metadata.available_sections
Returns: Workflow manifest, the complete requested body/slice, referenced tool schemas, and explicit response-selection/truncation metadata.
Work Plans
Agent-authored work plans are the local execution contract for one exact scope.
Implemented fields include scope, intent, typed steps, acceptance criteria,
produced artifacts, structural version, and append-only structural snapshots.
Plans live under ~/.pretorin/plans/<id>.json.
The version-1 JSON shape now has additive hierarchy fields. plan_kind defaults
to standalone, so existing files remain readable. A campaign parent has typed
campaign_context but no parent; a campaign_item has parent_plan_id and an
item context. Its UUID is deterministic from parent Plan plus item ID, and the
store validates that the parent exists and is a Campaign. Compliance artifact
bodies never belong in the hierarchy metadata.
create_plan
Persist an agent-authored work plan locally. Returns the full plan record including the generated plan id.
A plan must declare what it intends to do before it can carry writes. Omitting steps creates the plan in the draft state, and writes attributed to a draft plan are refused — call activate_plan with an ordered step list first. Supplying steps up front creates the plan active directly.
Parameters:
plan_kind(optional) —standalone(default),campaign, orcampaign_itemparent_plan_id(Campaign item only) — Existing parent Campaign Plan UUIDcampaign_type/campaign_context(Campaign Plans only) — Typed local Campaign identity, frozen selector/roster, expected outputs, runtime policy, and process criteriaworkflow_id(required) — Workflow id this plan executes (e.g.single-control)intent_summary(required) — One-paragraph statement of what the agent intends to do and why; used by future sessions to decide whether to resume or replacescope(optional) — Object withsystem_id,framework_id, andcontrol_idthis plan operates onintent_inputs_snapshot(optional) — Free-form snapshot of the inputs that shaped the plan (user prompt, active scope, etc.) so the audit trail captures the whysteps(optional) — Ordered list of intended steps; each hasindex(contiguous from 0),summary,kind(recipe,policy_link,issue,note, orother), and optionalref_id. Every step is createdpending— a step supplied in any other status is rejected, since creation declares intent and cannot back-date progress. Omit to create adraftthat must be activated before usecreated_by_agent(optional) — Identifier for the agent creating the plan (e.g.claude-code-1.2.3)acceptance_criteria(optional) — Typed conditions that must pass beforecomplete_plansucceeds (max 32). Platform-backed kinds includenarrative_min_chars,every_claim_cites_evidence,ai_narrative_reviewed,min_evidence_count_per_control, andall_required_spec_kinds_attested. Campaign children can also requireobjective_roster_dispositioned,grounded_claims_have_evidence,limitations_recorded,platform_writes_reconciled,platform_review_requested, andplatform_review_completed; those are evaluated from bounded local process records. The legacypreflight_recordedspelling is accepted only for persisted compatibility and now checks that the parent Campaign owns a frozen preflight snapshot.
Returns: The full plan record, including the generated plan id and its state (draft or active).
activate_plan
Declare the ordered execution steps for a draft plan and transition it to active.
start_task creates a scope-pinned draft for routed work — it knows the scope before the agent knows the implementation steps. Activation is where the agent states what it will actually do. Until it succeeds, the plan refuses step updates, completion, and any platform write carrying its plan_id.
For an interactive single-control task, the draft already contains the
workflow-required evidence-expectation-mapping step. Activation preserves it
and places it before assessment or narrative consumers after the agent’s
evidence work. For a Campaign child, the draft contains the coordinator-owned
mandatory milestone anchors. Include every returned anchor ref_id exactly
once and in its original order, keep campaign-preflight first and the final
mandatory anchor last, and author the concrete bounded work between them. Read
the returned Plan before sending attributed writes because those are the final
step indices. Campaign retries resume that activated structure; they do not
author a replacement Plan.
Parameters:
plan_id(required) — UUID-shaped id of the draft plan (fromstart_taskorcreate_plan)steps(required) — Ordered list, at least one entry. Each hasindex(contiguous from 0),summary,kind(recipe,policy_link,issue,note, orother), and optionalref_id,recipe_version,params. Every step must bepending— activation declares intent, it cannot back-date progressacceptance_criteria(optional) — Additional completion-gate criteria, added on top of any the workflow seeded into the draft. The workflow owns its Definition of Done, so seeded criteria always survive activation and cannot be removed; an entry whosekindis already seeded is ignored rather than overriding it. Omit (or send[]) to keep only the seeded criteria. The 32-criteria cap applies to the merged totalexpected_version(optional) — Optimistic-locking guard: the draft’sversionas the caller last read it. Activation incrementsversion, so a second caller holding the pre-activation number is told its view is staleactor(optional) — Agent identifier recorded on the initial structural snapshotreason(optional) — Why this execution contract is being activated
Returns: The activated plan record, with state: "active" and activated_at set.
Errors: Refused if the plan is neither a draft nor an adoptable legacy record (see below), if steps is empty, if step indices aren’t contiguous from zero, or if any step is not pending.
Legacy records: Also accepts a plan that is already active but declares no steps and was never activated — the shape start_task produced before the draft state existed. Completion requires at least one declared step, so supplying the steps here is the only route to completed for such a record; without it the plan could only be cancelled, stamping delivered work as “stopped early”. The same step rules apply, so the plan rejoins the normal contract rather than bypassing it.
mutate_plan_structure
Add, remove, or replace pending steps, or replace acceptance criteria. Every
call requires expected_version, actor, and reason; success increments
Plan.version and appends an immutable post-change snapshot. Runtime progress
and artifact recording do not increment the structural version. Workflow-owned
steps retain their required ordering, and acceptance-criteria replacement only
replaces caller-added criteria: workflow-required Definition-of-Done criteria
cannot be removed or weakened (an empty replacement clears only optional
criteria). Campaign child Plans cannot be structurally mutated after
activation; the child authors them at activation, after which the stable
structure is the retry contract.
Parameters:
plan_id(required)operation(required) — One ofadd_step,remove_step,replace_step,replace_acceptance_criteriaexpected_version(required) — CurrentPlan.version; a mismatch is rejected rather than appliedactor(required) — Who is making the structural change (1–200 chars)reason(required) — Why (1–2000 chars); recorded in the immutable snapshotstep_index(required forremove_stepandreplace_step) — Zero-based indexstep(required foradd_stepandreplace_step) — Object withindex,summary, andkind(recipe,policy_link,issue,note,other) required, plus optionalref_id,recipe_version,paramsacceptance_criteria(required forreplace_acceptance_criteria) — Up to 32 objects with a requiredkind(narrative_min_chars,every_claim_cites_evidence,ai_narrative_reviewed,min_evidence_count_per_control,all_required_spec_kinds_attested) and optionalparams
Returns: The updated plan with an incremented version.
get_plan
Return the full record of a previously-created plan. Use when resuming work from a prior session or auditing what was intended.
Parameters:
plan_id(required) — UUID-shaped plan id returned bycreate_plan
Returns: The full plan record.
list_recent_plans
List recent plans (newest first), with optional filtering by state, workflow, and scope. Returns compact summaries — call get_plan for the full record once a plan is selected. Use this at session start to find an existing plan to resume instead of creating a duplicate.
Parameters:
limit(optional) — Maximum number of plans to return (0–200, default20)state(optional) — Restrict results todraft,active,completed, orcancelledworkflow_id(optional) — Filter by workflow idsystem_id(optional) — Filter by system idframework_id(optional) — Filter by framework id (e.g.fedramp-moderate)control_id(optional) — Filter by control id
Returns: Compact plan summaries, newest first.
update_plan_step
Update one step’s status and/or outcome summary. Status transitions are guarded:
pending → in_progress | skipped; in_progress → completed | skipped;
terminal states are sticky. Skipping requires an explicit outcome_summary.
Workflow-required steps cannot be skipped. The single-control mapping step
also cannot be completed without evidence_mapping, a typed read-back record
from get_control_context after all links are written.
Parameters:
plan_id(required)step_index(required) — Index of the step to updatestatus(optional) — New status:pending,in_progress,completed, orskippedoutcome_summary(optional) — Short note about what the step actually produced. Required and non-empty whenstatusisskipped. May also be supplied alone to fill in a missing reason on an already-skipped step whose reason is blank; an existing reason cannot be overwrittenevidence_mapping(conditional) — Required when completingevidence-expectation-mapping. Containsactive_tier, all declaredexpectation_keys,bindings(expectation key → evidence-id list),intentionally_unbound(evidence_id+ reason), post-linkcoveredanduncoveredkey lists, andunbound_evidence_count. Every declared key must be classified; bound and intentionally unbound evidence cannot overlap.expected_version(optional) — Optimistic-locking guard. If supplied, the call returns a structuredversion_conflicterror when the plan’s on-disk version no longer matches
Returns: The updated plan record.
complete_plan
Mark a plan as completed. The Plan must be active, contain at least one step,
and have every step completed or explicitly skipped with a reason. Structural
gaps return plan_incomplete before acceptance evaluation. Failing typed
criteria return acceptance_failed; the Plan stays active in both cases.
Parameters:
plan_id(required)outcome_summary(optional) — One-paragraph summary of what the plan ultimately producedexpected_version(optional) — Optimistic-locking guard. If supplied, the call returns a structuredversion_conflicterror when the plan’s on-disk version no longer matchespostmortem(optional) — Friction analysis for the run; seefail_plan
Returns: The updated plan record.
fail_plan
Mark an active plan as failed after an unrecoverable execution error. The terminal transition is sticky — a failed plan cannot be walked back to active. Post-mortem delivery is best-effort and cannot change the failed result.
Parameters:
plan_id(required)outcome_summary(optional) — Bounded failure summaryexpected_version(optional) — Optimistic-locking guard, as oncomplete_planpostmortem(optional) — Structured friction analysis, accepted by all three terminal transitions:friction_detected(required, boolean)friction_points(required) — Up to 20 entries, each with a requiredcategory(one ofprerequisite_missing,recipe_required,scope_mismatch,version_conflict,permission_denied,validation_failure,repeated_attempt,premature_completion,plan_revised,step_failed,step_cancelled,resume_required,timeout,manual_intervention,unclear_recovery,other_bounded) and requiredsignal_refs, plus optionalstep_index,severity,occurrences, and a boundedsummaryanalysis(required) —{"mode": "model", "model": "..."}, optionally withharnessanalysis_version(optional)
Returns: The updated plan record.
cancel_plan
Mark a plan as cancelled. Allowed only from active. Idempotent: cancelling an already-cancelled plan is a no-op. Cannot cancel a completed plan.
Parameters:
plan_id(required)outcome_summary(optional) — Reason for cancellationexpected_version(optional) — Optimistic-locking guard. If supplied, the call returns a structuredversion_conflicterror when the plan’s on-disk version no longer matchespostmortem(optional) — Friction analysis for the run; seefail_plan
Returns: The updated plan record.