> ## Documentation Index
> Fetch the complete documentation index at: https://docs.formae.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# MCP tools and skills

> Every tool the formae MCP server exposes, and every skill it ships, grouped by what they do.

The formae MCP server exposes the tools below, and ships the skills that use them.
To install it and connect an assistant, see
[AI assistants](https://docs.formae.ai/documentation/guides/ai-coding-assistants.md).

The two layers differ: tools are the API access, skills are the workflows that use
them safely.

Every tool that talks to an agent accepts an optional `profile` argument, which
targets one formae environment for a single call without changing which profile is
active. See
[Targeting a specific environment](https://docs.formae.ai/documentation/guides/ai-coding-assistants.md#targeting-a-specific-environment).

## Tools

### Read-only

| Tool | Description |
| - | - |
| `list_resources` | Query resources with optional filters |
| `list_stacks` | Retrieve all stacks |
| `list_targets` | Query configured cloud targets |
| `get_command_status` | Get status of a specific command |
| `get_command_desired_delta` | Retrieve recorded changes and deletion guidance for updating source after a terminal command |
| `list_commands` | List commands with optional filters |
| `get_agent_stats` | Retrieve agent statistics |
| `check_health` | Health check for the agent |
| `list_changes_since_last_reconcile` | List changes since last reconcile |
| `extract_resources` | Extract resources as Pkl code |
| `list_policies` | List reusable policies and the stacks they're attached to |
| `search_hub_plugins` | Search the live plugin hub by keyword or resource type |
| `get_hub_plugin` | Get details for a specific hub plugin |
| `list_plugin_examples` | List version-matched examples for a hub plugin |
| `get_plugin_example` | Fetch a specific example from a hub plugin |
| `list_agent_plugins` | Report the resource plugins the connected installation has, and whether that installation is hosted or self-hosted |
| `list_generators` | List generators: what draws a credential and, where one declares a cadence, rotates it |

> [!NOTE]
>
> `list_agent_plugins` is the one to call before `search_hub_plugins` when authoring,
> because it decides whether the hub catalogue is relevant at all. On formae Cloud the
> set is closed: plugins ride the agent image, so one that is absent cannot be used and
> authoring a new plugin will not make it available. It also reports the schema package
> version to pin, which differs from the installed version for a `-dev` build.
>
> It lists the *agent's* plugins, which is not what the local `formae plugin list`
> reports — that one reads this machine's package store.

`list_generators` returns each generator's label, stack, type, generation spec,
rotation interval, last committed rotation and bound resources. It never returns the
drawn value. An agent older than the feature reports none rather than failing.

### Mutation

| Tool | Description |
| - | - |
| `apply_forma` | Deploy or update infrastructure |
| `destroy_forma` | Remove infrastructure by file or query |
| `cancel_commands` | Cancel running commands |
| `force_sync` | Trigger immediate resource synchronization |
| `force_discover` | Trigger immediate resource discovery |
| `force_check_ttl` | Trigger an immediate TTL expiry sweep across stacks |
| `force_reconcile_stack` | Force a one-shot reconcile on a stack with an auto-reconcile policy |
| `create_inline_policy` | Plan a TTL or auto-reconcile policy edit on a stack |

### Policies

`create_inline_policy` above governs a single stack. A **standalone** policy is
declared once and attached to as many stacks as you like. See
[Policies](https://docs.formae.ai/documentation/concepts/policy.md).

These four plan an edit and return a Pkl snippet with the line range to apply it at.
They modify nothing themselves: your assistant makes the edit, then simulates and
applies with `apply_forma`.

| Tool | Description |
| - | - |
| `create_standalone_policy` | Plan the declaration of a reusable policy at the top level of a forma block. Attaches it to nothing on its own |
| `attach_standalone_policy` | Plan attaching one to a stack, creating the `policies` listing if the stack has none |
| `detach_standalone_policy` | Plan removing the reference from one stack. The policy stays declared, and stays attached to any others |
| `delete_standalone_policy` | Plan deleting the declaration itself |

Two refusals are deliberate. `attach_standalone_policy` rejects a stack that already
carries a policy of the same type, inline or standalone, because a stack holds only
one policy per type; the error names the conflict. `delete_standalone_policy` refuses
while the policy is still attached anywhere, and lists the stacks — detach and apply
first.

Deletion is also order-sensitive: edit the source to remove the declaration *before*
running the destroy the tool hands back. In that order, a reconcile landing between
the two steps sees no policy in any forma and does nothing. Reversed, it would
recreate the policy.

These require a project pinning the formae Pkl schema at 0.82.0 or later, which is
when policies arrived.

### Local authoring context

These tools select and prepare local source without changing cloud resources.
A profile chooses the formae installation; a codebase context chooses where the
assistant maintains source for the current operation.

| Tool | Description |
| - | - |
| `get_codebase_context` | Resolve registered project candidates for the installation and harness directory, or select no codebase |
| `list_codebases` | List locally registered projects |
| `register_codebase` | Register a maintained project and its stack scope |
| `unregister_codebase` | Remove a local registration without deleting project files |
| `prepare_authoring` | Retrieve complete desired declarations and render Pkl with dependencies into a disposable directory |
| `set_drift_preference` | Save your standing answer to the out-of-band change question, across sessions and codebases |

`set_drift_preference` stores one of two choices for an installation: keep asking
about every out-of-band change, or automatically keep the ones that do not conflict
with your edits. Your assistant offers it once, after you have explicitly chosen to
keep a change — keeping one change is not consent to the policy, and no answer leaves
the setting alone. The preference is read back through `get_codebase_context`, never
authorizes a force or overrides a conflict, and you can change it whenever you like.
Conflicts, removals and ordinary apply confirmation are unaffected.

The assistant retains temporary authoring files through simulation, submission
and retry inspection, then removes them after the outcome is known or an unsent
preview is abandoned. An interrupted session can leave those files behind; they
are not registered as a maintained project.

### Profiles

Requires formae >= 0.87.0. Manage named formae environments (endpoint + targets)
from your assistant.

| Tool | Description |
| - | - |
| `list_profiles` | List configuration profiles and which one is active |
| `current_profile` | Show the active profile |
| `use_profile` | Switch the active profile (global; only on explicit "change my default" requests) |
| `save_profile` | Snapshot the active profile under a new name |
| `create_profile` | Create a new profile from the starter template |
| `delete_profile` | Delete a profile (cannot be the active one) |
| `diff_profiles` | Compare two profiles, or one against the active |
| `read_profile` | Return a profile's Pkl contents |
| `write_profile` | Replace a profile's Pkl (overwrite-only; refuses the active profile) |

### formae Cloud

These cover signing in to [formae Cloud](https://docs.formae.ai/documentation/get-started/quickstart-cloud.md)
and connecting a cloud account to it. A self-hosted agent needs none of them.

Signing in takes two calls, because you do the browser step in between:

| Tool | Description |
| - | - |
| `login` | Start signing in. Returns a URL, or a device code when no browser can open where you are working |
| `complete_login` | Finish the sign-in `login` started, once you confirm you are done |

`login` needs no profile and works on a machine where nothing is configured yet,
which is the case it exists for. Calling it with a session already open is harmless:
it reports that session and writes nothing. `complete_login` reports who signed in,
the profiles formae wrote for the installations your grants cover, and which profile
is now active; calling it without a preceding `login` is an error rather than a no-op.

Connecting a cloud account then differs by provider, because how much each one can
automate differs:

| Tool | Description |
| - | - |
| `list_cloud_connections` | List the accounts this installation has registered |
| `list_aws_profiles` | List your local AWS profiles and the account each resolves to, so you can pick one |
| `provision_cloud_role` | **AWS.** Create the IAM role formae assumes and register it, in one call, using the profile you picked |
| `connect_cloud_account` | **AWS.** Compute a CloudFormation quick-create link for you to apply yourself |
| `register_cloud_role` | Record the role the applied stack produced, completing `connect_cloud_account` |
| `connect_gcp_project` | **GCP.** Create the workload identity federation, grant it access to the project, and register it, in one call |
| `connect_azure_subscription` | **Azure.** Create the managed identity, grant it access to the subscription, and register it, in one call |
| `get_azure_trust_template` | **Azure.** Return a portal link opening an ARM template prefilled with this installation's coordinates |
| `register_azure_trust` | Register the tenant id and client id that template outputs |

AWS has two routes. With credentials on the machine, `list_aws_profiles` then
`provision_cloud_role` does the whole thing — it creates a real IAM role immediately,
plus the account-global OIDC identity provider if the account has none yet. Without
them, `connect_cloud_account` only computes a link; you apply the stack in your own
browser under your own session, and `register_cloud_role` records what it produced.
Azure splits the same way, between `connect_azure_subscription` and the
`get_azure_trust_template` / `register_azure_trust` pair. GCP has no console
equivalent, so `connect_gcp_project` is the only route.

> [!WARNING]
>
> The one-call tools grant broad access and act immediately. `connect_gcp_project`
> grants editor on the project plus the ability to manage its IAM;
> `connect_azure_subscription` grants Contributor plus User Access Administrator, which
> together are close to owner. Your assistant tells you before anything is created.
>
> None of these infer which account you mean — you are always asked for the account id,
> project id or subscription id, because provisioning trust into the wrong one is not a
> mistake a default should be able to make.

Re-running a connect flow is safe: reporting that an account is already connected with
the same role or identity is a success, not a conflict. A listed connection is
*registered*, not verified — it does not confirm formae can use the role. If
`list_cloud_connections` reports that it could not determine the listing, that means
unknown, not "nothing is connected".

`register_azure_trust` validates the shape of the coordinates only. It does not check
that the identity exists, trust the formae issuer, or grant anything.

### Bug reports

Available on formae Cloud. Preparing and sending are separate tools so you see exactly
what would leave your machine before any of it does.

| Tool | Description |
| - | - |
| `prepare_bug_report` | Build a sanitized report and return the full preview, the support recipient and a `report_id`. Nothing is uploaded |
| `submit_bug_report` | Send a prepared report to the recipient shown in its preview |

The preview is immutable, and `submit_bug_report` takes only the `report_id` and your
confirmation, so what is sent is exactly what you saw. Reports expire an hour after
preparation and are scoped to the MCP session that made them. Retrying delivery means
reusing the same `report_id`; if the configured recipient has changed, you get a new
preview to authorize instead. Submitting retries no infrastructure operation.

Local CLI diagnostics are included only where relevant — hosted agent logs are already
available to support, and inventories, whole forma files, transcripts and arbitrary log
files are never attached.

> [!NOTE]
>
> Self-hosted users report bugs through
> [GitHub issues](https://github.com/platform-engineering-labs/formae-mcp/issues) or
> Discord instead.

## Skills

Skills are workflows your assistant follows when you ask for an infrastructure
task. They enforce safe practices like simulating before applying and confirming
before destructive operations.

| Skill | Description |
| - | - |
| `/formae-author` | Front door for authoring new infrastructure: triages intent, infers plugins, dispatches to the focused skills below |
| `/formae-project-init` | Scaffold a new forma project with the right layout and config |
| `/formae-deps` | Add or remove plugin schema dependencies in a project |
| `/formae-stack-design` | Design how resources are grouped into stacks |
| `/formae-apply` | Deploy infrastructure (simulate, confirm, apply) |
| `/formae-patch` | Targeted change without a full reconcile |
| `/formae-rename` | Rename a resource's label via `alias` without recreating the cloud object |
| `/formae-destroy` | Tear down resources, stacks, or environments |
| `/formae-fix-code-drift` | Resolve out-of-band changes centrally and update an optional selected codebase |
| `/formae-policy` | Set, remove, or inspect TTL and auto-reconcile policies on a stack |
| `/formae-discover` | Find unmanaged resources in cloud accounts |
| `/formae-import` | Bring unmanaged resources under formae management |
| `/formae-status` | Check running commands, deployment progress, and failures |
| `/formae-stacks` | View infrastructure stacks and resource counts |
| `/formae-resources` | Query resources by type, stack, label, or management status |
| `/formae-targets` | List cloud targets and configured regions |
| `/formae-plugin-new` | Scaffold a new resource plugin from scratch |
| `/formae-plugin-add-resource` | Add a resource type to an existing plugin |
| `/formae-config` | Manage formae config profiles (requires formae >= 0.87.0) |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.