# Required MCP tools

The `grcitsm-analyst` plugin operates your GRCITSM tenant through the **GRCITSM MCP tool catalog**, exposed by the MCP server registered as `grcitsm` (see SETUP.md). Your tenant's GRCITSM integration runbook provisions this catalog. Run `/grcitsm-analyst:setup` to verify your server exposes everything below.

Tool names appear on your server with a `CF_` prefix (e.g. `CF_get_asset` for `get_asset`); the plugin's skills and agents refer to them by bare name.

## Ticket operations

| Tool | Purpose |
|---|---|
| `create_new_ticket` | Create a ticket logged against a specified user |
| `ticket_templates` | Optional pair (with `apply_ticket_template`) — list the tenant's native ticket/project template catalog; parent `Ticket Template` rows are apply-targets, `Child Template` rows are sub-ticket definitions. Agents skip the template check silently when this pair is absent |
| `apply_ticket_template` | Optional pair (with `ticket_templates`) — create a ticket or project from a template in one server-side expansion (`template_id` + `site_id` required; optional `user_email` requester override and `summary`); verify via `get_ticket` read-back |
| `get_ticket` | One ticket by ID — identity, lifecycle, assignment, category, custom fields |
| `search_tickets` | Semantic + keyword ticket search |
| `update_ticket_fields` | Generic ticket update — native FKs + custom fields, any ticket type |
| `agent_note` | Add a billable Action (note + time + charge rate, optional status/priority/category updates) |
| `assign_agent` | Reassign a ticket's owning agent |
| `set_ticket_parent` | Set a ticket's parent |
| `set_ticket_assets` | Set the full list of linked assets on a ticket |
| `set_ticket_client_site` | Reassign a ticket's client and site |
| `set_ticket_sla_and_priority` | Set priority (SLA-scoped) and optionally SLA |
| `ticket_summary` | Bulk ticket roll-up across the tenant (pair with `get_ticket` above for point reads / per-id loops) |
| `open_issues` / `closed_issues` | Leaf-level Issue tickets with full hierarchy context |
| `vulnerability_deviations` | Vulnerability Deviation Request tickets in FedRAMP VDR format |

## Ticket schema and instance lookups

| Tool | Purpose |
|---|---|
| `ticket_type_fields` | Custom fields per ticket type — call before any ticket update |
| `ticket_type_allowed_statuses` | Allowed status transitions per ticket type |
| `ticket_type_allowed_categories` | Allowed main categories per ticket type |
| `statuses` | Ticket status catalog (read-only enum) |
| `categories` | Ticket category catalog |
| `slas_and_priorities` | SLA catalog with per-SLA priority labels |
| `agents` | Agent (user) catalog — resolves agent_id for assignment |
| `client_details` | Client (account) catalog |
| `users` | End-user catalog — one row per active end user (User ID, Display Name, Email, Client ID/Name, Site ID/Name, Is General User); resolves a site's General User for requester writes |
| `charge_rates` | Charge-rate catalog (used with `agent_note` billable notes) |

## Asset operations

| Tool | Purpose |
|---|---|
| `create_asset` | Create an asset (any type); returns the new asset_id |
| `get_asset` | Point read — one asset by ID (read-back after writes; use in a post-summary per-id loop) |
| `update_asset` | Generic asset update — Asset Fields + Custom Fields in one call |
| `asset_summary` | Bulk asset roll-up — one row per Client/Site/Type[/Status], pipe-delimited id lists and `<asset id>:<inventory_number>` pairs for AFUUID→id bulk resolution (pair with `get_asset` above for point reads) |
| `active_inventory` | Active asset inventory (Cloud + Hardware bulk; excludes the SSP spine) in FedRAMP IIW / OSCAL format |
| `set_asset_relationships` | Set the full downstream-asset list on an asset |
| `asset_relationship_restrictions` | Allowed (upstream × downstream × relationship) triples — call before relationship writes |

## Asset schema lookups

| Tool | Purpose |
|---|---|
| `asset_types` | Asset-type catalog — call before `asset_type_fields` |
| `asset_type_fields` | Every field on every asset type — call before writing asset CFs; `[Allowed Values]` is authoritative for static lookups only (write-semantics § 3.11) |
| `asset_type_allowed_statuses` | Allowed status values per asset type |

## System (Site) information

| Tool | Purpose |
|---|---|
| `system_information` | Per-system SSP header (FIPS-199 level, baselines, identifiers) |
| `update_system_information` | Update Site native fields + custom fields |
| `system_pocs` | FedRAMP-required Points of Contact per system |
| `site_fields` | Every custom field on a Site (System Information panel); `[Allowed Values]` is authoritative for static lookups only (write-semantics § 3.11) |

## Compliance control catalog

| Tool | Purpose |
|---|---|
| `baseline_catalog` | Baseline dimension catalog — one row per FedRAMP/CMMC/Drata baseline |
| `lookup_controls` | Combined (control × baseline) catalog row |
| `lookup_control_details` | Canonical baseline-agnostic control/KSI/practice record |
| `lookup_control_parameters` | Per-(baseline × class) parameter override layer |
| `lookup_requirements` | Sub-requirement / assessment-objective entry |
| `control_baselines_summary` | Per-baseline control membership counts |
| `control_details_summary` | Per-(framework × entity type) control ID lists |
| `control_parameters_summary` | Per-baseline override coverage |
| `control_requirements_summary` | Per-baseline sub-requirement counts |

## Component and implementation-statement library

| Tool | Purpose |
|---|---|
| `component_definitions_summary` | Reusable component-definition library summary |
| `lookup_component_definition` | One component-definition library row |
| `update_component_from_library` | Apply a stored definition to an existing Component asset |
| `implementation_statement_definitions_summary` | Reusable implementation-statement library summary |
| `lookup_implementation_statement_definition` | One implementation-statement library row |
| `update_implementation_statement_from_library` | Apply a stored IS definition (UUID/Title/Statement + baseline-gated framework CFs) to an existing Implementation Statement asset — one baseline per call; leaves per-instance policy fields (implementation state, control origination, responsible role) to `update_asset` |

## SSP reconciliation

| Tool | Purpose |
|---|---|
| `reconcile_ssp_assets` | Create any missing SSP framework assets across Sites |
| `reconcile_ssp_relationships_cap_component` | Reconcile Capability → Component links (rel 6, driven by Component `inventory_number` + library `CFComponentCapability`) |
| `reconcile_ssp_relationships_ci_ir` | Reconcile Control Implementation → Implemented Requirement links |
| `reconcile_ssp_relationships_ir_is` | Reconcile Implemented Requirement → Implementation Statement links |
| `reconcile_ssp_relationships_ci_sp` | Reconcile Control Implementation → Set Parameter links (rel 11, system-wide ODPs) |
| `reconcile_ssp_relationships_ir_sp` | Reconcile Implemented Requirement → Set Parameter links (rel 12, per-control ODPs) |

## Validation tickets

| Tool | Purpose |
|---|---|
| `create_validation_tickets` | Bulk-scaffold the FedRAMP 20x KSI validation tickets (top-level Validation-type per-KSI tickets, class-aware) on every 20x Site missing them — idempotent sweep; use instead of creating KSI tickets one by one |
| `get_validations` | Read validation run rows from a validation check ticket |
| `create_validations` | Upsert validation run rows (runs-only — check definition lives on the ticket) |

## Knowledge base

| Tool | Purpose |
|---|---|
| `search_knowledge_base` | Semantic + keyword KB search |
| `get_one_article` | Curated 5-field KB article summary |
| `create_kb_article` | Create a KB article |
| `update_kb_article` | Update a KB article (chainable for read-merge-write) |

## Reports

| Tool | Purpose |
|---|---|
| `halo_reports` | Catalog of reports defined in the tenant |

## Runbook introspection (optional debug pair)

| Tool | Purpose |
|---|---|
| `get_runbooks` | Optional pair (with `get_runbook_logs`) — list the tenant's runbooks with version and active flag; the entry point for debugging template applies and other runbook-backed writes |
| `get_runbook_logs` | Optional pair (with `get_runbooks`) — run logs for one runbook (GUID from `get_runbooks`' `[Runbook ID]` column); the debug path when a write returns transport success but the `get_ticket` read-back fails. When the pair is absent, report the failure to your platform operator |

## Connector auth and subagent / executor inheritance

The catalog reaches your tenant one of two ways, and the plugin is prefix-agnostic about which:

- a **local stdio server** — tools appear as `mcp__grcitsm__*` (or `mcp__GRCITSM__*`), or
- a **claude.ai-hosted OAuth connector** — tools appear as `mcp__claude_ai_<connector display name>__*`, with spaces mapped to underscores. A connector named plainly `GRCITSM` yields `mcp__claude_ai_GRCITSM__*`; an environment-qualified one such as `GRCITSM Halo Gov` yields `mcp__claude_ai_GRCITSM_Halo_Gov__*`. Each is a distinct server segment, not a variant of the same one.

**Subagents and dynamic-workflow `agent()` executors inherit the parent session's authenticated MCP session** — including OAuth connectors — with no re-auth, when the server is attached to the parent session (a string reference shares the parent's already-authenticated session). Empirically verified 2026-07-16: a workflow-spawned agent called `mcp__claude_ai_GRCITSM__CF_client_details` and got tenant data with no consent prompt.

Two caveats, both of which have bitten the `halo-apply` executor fleet:

1. **The subagent's own `tools:` allowlist gates access.** Auth being inherited is necessary but not sufficient — the agent must also be *permitted* the tools. An agent whose frontmatter `tools:` omits a connector's `mcp__<server>__*` pattern cannot load or call any of that connector's tools even though it is authenticated and present in the session — the apply fleet then silently applies 0/N. (It is NOT an OAuth-inheritance failure, despite looking like one.)

   **There is no family glob, and no allowlist is portable.** The server segment is matched literally, so `mcp__claude_ai_GRCITSM__*` covers only the connector named exactly `GRCITSM`; the trailing `__` is part of the literal, and every environment-qualified name (`GRCITSM Dev`, `GRCITSM Halo Gov`) falls outside it. Measured 2026-08-03 against a session holding four GRCITSM connectors, dispatching one probe subagent per pattern:

   | Allowlist pattern | MCP tools visible |
   |---|---|
   | `mcp__claude_ai_GRCITSM_Halo_Gov__*` (exact server) | 73 |
   | `mcp__claude_ai_GRCITSM_*` (single-underscore prefix) | 0 |
   | `mcp__claude_ai_GRCITSM*__*` (mid-pattern wildcard) | 0 |
   | `mcp__*` (bare) | 0 |
   | *`tools:` omitted, narrowed by `disallowedTools:`* | **340, all 11 servers** |

   Only an exact server name works, so an allowlist can never reach a connector whose name is unknown at authoring time — which is every client-facing deployment of this plugin. **The portable construction is to omit `tools:` and restrict with `disallowedTools:`**, which inherits every MCP server the session holds regardless of name (and still yields `Bash`, `Write`, and the auto-provided `ToolSearch`). `halo-action-executor` is built that way; its scope is enforced by the action-file contract rather than by a tool list. Note: `ToolSearch` is NOT a listable frontmatter tool (the structure validator rejects it) — it is harness-provided automatically whenever MCP tools are in scope, whether they arrive via an exact-server allowlist or via inheritance when `tools:` is omitted.
2. **Interactive OAuth consent does not run headlessly.** If a connector needs auth and no token is stored, the run continues *without* that server's tools and reports `needs-auth` in the mcp_servers status — it will not pop a browser consent flow inside a workflow. For dynamic/headless runs, complete the OAuth flow in-app first so a token is stored; then the executors inherit it.

Net: on a claude.ai-connected tenant, halo-apply's fleet works as long as the session holds the authenticated connector — the executor no longer constrains which connector that is. If you fork the executor and add a `tools:` allowlist, you take on the burden of naming every connector it will ever face, and the failure mode for one you miss is silent.
